tdls.c revision 43cb578dfe2c492257636f6234a24178ed27789e
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - TDLS 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010-2011, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/os.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_ie.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_i.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_FRAME BIT(0) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_ALT_RSN_IE BIT(1) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DIFF_BSSID BIT(2) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_SHORT_LIFETIME BIT(3) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5) 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_LIFETIME BIT(6) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_CONCURRENT_INIT BIT(7) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DECLINE_RESP BIT(9) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10) 3621de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#define TDLS_TESTING_WRONG_MIC BIT(11) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tdls_testing = 0; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TPK_LIFETIME 43200 /* 12 hours */ 41f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M1_RETRY_COUNT 3 42f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M1_TIMEOUT 5000 /* in milliseconds */ 43f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M2_RETRY_COUNT 10 44f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt#define TPK_M2_TIMEOUT 500 /* in milliseconds */ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MIC_LEN 16 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TIMEOUT_LEN 4 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_ftie { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* FTIE */ 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic_ctrl[2]; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[TDLS_MIC_LEN]; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */ 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by optional elements */ 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_timeoutie { 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Timeout IE */ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 interval_type; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 value[TDLS_TIMEOUT_LEN]; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_lnkid { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Link Identifier IE */ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN]; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 init_sta[ETH_ALEN]; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 resp_sta[ETH_ALEN]; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TDLS frame headers as per IEEE Std 802.11z-2010 */ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_frame { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */ 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 category; /* Category */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action; /* Action (enum tdls_frame_type) */ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer); 85d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Duttstatic void wpa_tdls_disable_peer_link(struct wpa_sm *sm, 86d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt struct wpa_tdls_peer *peer); 87b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtstatic int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, 88b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt u16 reason_code); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MAX_IE_LEN 80 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define IEEE80211_MAX_SUPP_RATES 32 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_peer { 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *next; 968da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt unsigned int reconfig_key:1; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator; /* whether this end was initiator for TDLS setup */ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; /* other end MAC address */ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_i_len; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_p_len; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; /* Selected cipher (WPA_CIPHER_*) */ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kck[16]; /* TPK-KCK */ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } tpk; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_set; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_success; 11573b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt int tpk_in_progress; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk_timer { 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dest[ETH_ALEN]; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count; /* Retry Count */ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timer; /* Timeout in milliseconds */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code; /* TDLS frame type */ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status_code; 124df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u32 peer_capab; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int buf_len; /* length of TPK message for retransmission */ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; /* buffer for TPK message */ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } sm_tmr; 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 capability; 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t supp_rates_len; 133f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 134f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct ieee80211_ht_capabilities *ht_capabilities; 13533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt struct ieee80211_vht_capabilities *vht_capabilities; 136f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 137f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 qos_info; 138f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 13951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt u16 aid; 14051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 141f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *ext_capab; 142f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt size_t ext_capab_len; 143344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 144344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt u8 *supp_channels; 145344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt size_t supp_channels_len; 146344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 147344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt u8 *supp_oper_classes; 148344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt size_t supp_oper_classes_len; 149df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 150df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u8 wmm_capable; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_get_privacy(struct wpa_sm *sm) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Get info needed from supplicant to check if the current BSS supports 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * security. Other than OPEN mode, rest are considered secured 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake. 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise_cipher != WPA_CIPHER_NONE; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr, 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, 0, NULL, 0, NULL, 0) < 0) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from " 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the driver"); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_len; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (peer->cipher) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = WPA_ALG_CCMP; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_NONE: 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: " 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NONE - do not use pairwise keys"); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d", 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver"); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code, u8 dialog_token, 220df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u16 status_code, u32 peer_capab, 221df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt const u8 *buf, size_t len) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, 224df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt status_code, peer_capab, buf, len); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, 229df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u8 dialog_token, u16 status_code, u32 peer_capab, 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *msg, size_t msg_len) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u " 235b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u", 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dest), action_code, dialog_token, status_code, 237b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt peer_capab, (unsigned int) msg_len); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, 240df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt status_code, peer_capab, msg, msg_len)) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to send message " 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == WLAN_TDLS_SETUP_CONFIRM || 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_TEARDOWN || 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_DISCOVERY_REQUEST || 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action_code == WLAN_TDLS_DISCOVERY_RESPONSE) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* No retries */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0) 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "retry " MACSTR, MAC2STR(dest)); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 265f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (action_code == WLAN_TDLS_SETUP_RESPONSE) { 266f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.count = TPK_M2_RETRY_COUNT; 267f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.timer = TPK_M2_TIMEOUT; 268f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } else { 269f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.count = TPK_M1_RETRY_COUNT; 270f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt peer->sm_tmr.timer = TPK_M1_TIMEOUT; 271f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Copy message to resend on timeout */ 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = action_code; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token = dialog_token; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code = status_code; 278df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->sm_tmr.peer_capab = peer_capab; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = msg_len; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = os_malloc(msg_len); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.buf, msg, msg_len); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered " 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 288f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 289f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (peer->sm_tmr.timer % 1000) * 1000, 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 2966a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt u16 reason_code) 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3006a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code); 3016a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt /* disable the link after teardown was sent */ 302d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.count) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count--; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Retrying sending of message " 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) { 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No retry buffer available " 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for action_code=%u", 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* resend TPK Handshake Message to Peer */ 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token, 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code, 335df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->sm_tmr.peer_capab, 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf, 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len)) { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to retry " 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transmission"); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 343f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 344f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (peer->sm_tmr.timer % 1000) * 1000, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request"); 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_do_teardown(sm, peer, 3516a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm, 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code) 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == peer->sm_tmr.action_code) { 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for " 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "action_code=%u", action_code); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Cancel Timeout registered */ 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* free all resources meant for retry */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count = 0; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.timer = 0; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = 0; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = 0xff; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout " 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Unknown action_code=%u)", action_code); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer, 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *own_addr, const u8 *bssid) 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_input[SHA256_MAC_LEN]; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce[2]; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[3 * ETH_ALEN]; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE Std 802.11z-2010 8.5.9.1: 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPA_NONCE_LEN; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = WPA_NONCE_LEN; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->inonce; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->rnonce; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->rnonce; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->inonce; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(2, nonce, len, key_input); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_input, SHA256_MAC_LEN); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is N_KEY really included in KDF Context and if so, in which 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * presentation format (little endian 16-bit?) is it used? It gets 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * added by the KDF anyway.. 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, own_addr, ETH_ALEN); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN); 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, peer->addr, ETH_ALEN); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &peer->tpk, sizeof(peer->tpk)); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.kck, sizeof(peer->tpk.kck)); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.tk, sizeof(peer->tpk.tk)); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = 1; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsnie: Pointer to the beginning of RSN IE used for handshake 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeoutie: Pointer to the beginning of Timeout IE used for handshake 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid, 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsnie, const u8 *timeoutie, 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_lnkid *_lnkid; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] + 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + timeoutie[1] + 2 + ftie[1]; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _lnkid = (const struct wpa_tdls_lnkid *) lnkid; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) TDLS initiator STA MAC address */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->init_sta, ETH_ALEN); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) TDLS responder STA MAC address */ 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Transaction Sequence number */ 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Link Identifier IE */ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5) RSN IE */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, rsnie, 2 + rsnie[1]); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + rsnie[1]; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6) Timeout Interval IE */ 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, timeoutie, 2 + timeoutie[1]); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + timeoutie[1]; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @trans_seq: Transaction Sequence Number (4 - Teardown) 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rcode: Reason code for Teardown 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dtoken: Dialog Token used for that particular link 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode, 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken, const u8 *lnkid, 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lnkid == NULL) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) + 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(trans_seq) + 2 + ftie[1]; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) Link Identifier IE */ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) Reason Code */ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rcode); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rcode); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Dialog token */ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = dtoken; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Transaction Sequence number */ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic(u8 trans_seq, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const u8 *timeoutie, 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_ftie *ftie) 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, timeoutie, (u8 *) ftie, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, ftie->mic, 16) != 0) { 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - " 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC", 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic, 16); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC", 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic, 16); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, " 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK not set - dropping packet"); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic_teardown( 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const struct wpa_tdls_ftie *ftie) 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken, lnkid, (u8 *) ftie, mic); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, ftie->mic, 16) != 0) { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - " 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown " 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MIC, TPK not set - dropping packet"); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx) 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * On TPK lifetime expiration, we have an option of either tearing down 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the direct link or trying to re-initiate it. The selection of what 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to do is not strictly speaking controlled by our role in the expired 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * link, but for now, use that to select whether to renew or tear down 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the link. 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - try to renew", MAC2STR(peer->addr)); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_start(sm, peer->addr); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - tear down", MAC2STR(peer->addr)); 6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_do_teardown(sm, peer, 6296a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR, 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 6408da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; 64273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 0; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 645f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ht_capabilities); 646f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ht_capabilities = NULL; 64733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_free(peer->vht_capabilities); 64833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt peer->vht_capabilities = NULL; 649f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ext_capab); 650f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab = NULL; 651344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_channels); 652344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels = NULL; 653344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_oper_classes); 654344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes = NULL; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = peer->rsnie_p_len = 0; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = 0; 657df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->qos_info = 0; 658df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->wmm_capable = 0; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = peer->tpk_success = 0; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&peer->tpk, 0, sizeof(peer->tpk)); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->inonce, 0, WPA_NONCE_LEN); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->rnonce, 0, WPA_NONCE_LEN); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_type = WLAN_EID_LINK_ID; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_len = 3 * ETH_ALEN; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 682b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtstatic int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, 683b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt u16 reason_code) 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid lnkid; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(addr)); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token = peer->dtoken; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR, 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = 0; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) { 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* To add FTIE for Teardown request and compute MIC */ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += sizeof(*ftie); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += 170; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(ielen + 1); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 72751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using the recent nonce which should be for CONFIRM frame */ 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 168; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake", 7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (u8 *) ftie, pos - (u8 *) ftie); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, &lnkid); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code, 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token, (u8 *) &lnkid, (u8 *) ftie, 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: register for a Timeout handler, if Teardown is not received at 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the other end, then try again another time */ 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* request driver to send Teardown using this FTIE */ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, 762df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt reason_code, 0, rbuf, pos - rbuf); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code) 7701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 7721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 7771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 7781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 7791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) { 7821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " for link Teardown", MAC2STR(addr)); 7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!peer->tpk_success) { 7881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR 7891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " not connected - cannot Teardown link", MAC2STR(addr)); 7901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 7911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7936a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt return wpa_tdls_do_teardown(sm, peer, reason_code); 7941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 79738ffd8879e7990491033bf20568212e8c3472b48Sunil Duttstatic void wpa_tdls_disable_peer_link(struct wpa_sm *sm, 79838ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt struct wpa_tdls_peer *peer) 79938ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt{ 80038ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 80138ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_peer_free(sm, peer); 80238ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt} 80338ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt 80438ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt 80543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidtvoid wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr) 8061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 8071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 8081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 8101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 8111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 8121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 81443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (!peer || !peer->tpk_success) { 81543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR 81643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt " not connected - cannot teardown unreachable link", 81743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt MAC2STR(addr)); 81843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt return; 81943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } 82043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 82143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_tdls_is_external_setup(sm)) { 82243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt /* 82343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * Disable the link, send a teardown packet through the 82443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * AP, and then reset link data. 82543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt */ 82643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr); 82743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_send_teardown(sm, addr, 82843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE); 82943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_peer_free(sm, peer); 83043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } else { 83138ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 83243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt } 8331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 836e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtconst char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr) 837e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 838e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct wpa_tdls_peer *peer; 839e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 840e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 841e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "disabled"; 842e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 843e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 844e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 845e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt break; 846e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 847e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 848e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (peer == NULL) 849e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "peer does not exist"; 850e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 851e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (!peer->tpk_success) 852e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "peer not connected"; 853e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 854e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return "connected"; 855e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 856e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 857e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr, 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = NULL; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(src_addr)); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code = WPA_GET_LE16(pos); 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (reason code %u)", MAC2STR(src_addr), reason_code); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown"); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS " 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown"); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ftie; 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown"); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TDLS Teardown is right */ 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken, peer, 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) lnkid, ftie) < 0) { 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS " 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown Request from " MACSTR, MAC2STR(src_addr)); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ftie: 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request the driver to disable the direct link and clear associated 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keys. 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 92738ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_send_error - To send suitable TDLS status response with 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * appropriate status code mentioning reason for error/failure. 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst - MAC addr of Peer station 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @tdls_action - TDLS frame type for which error code is sent 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @status - status code mentioning reason 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tdls_action, u8 dialog_token, u16 status) 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (action=%u status=%u)", 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dst), tdls_action, status); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, 947df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 0, NULL, 0); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpa_tdls_peer * 9524b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtwpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing) 9531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 9541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 9551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9564b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (existing) 9574b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt *existing = 0; 9584b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 9594b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) { 9604b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (existing) 9614b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt *existing = 1; 9624b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return peer; /* re-use existing entry */ 9634b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 9644b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt } 9654b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 9661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR, 9671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(addr)); 9681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer = os_zalloc(sizeof(*peer)); 9701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) 9711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 9721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(peer->addr, addr, ETH_ALEN); 9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->next = sm->tdls; 9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls = peer; 9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return peer; 9781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 9791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m1(struct wpa_sm *sm, 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer) 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos, *count_pos; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 991d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No security used on the link"); 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsnie; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK Handshake Message 1: 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I, 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Timeout Interval IE)) 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Filling RSN IE */ 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_i; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AES-CCMP is the default Encryption preferred for TDLS, so 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSN IE is filled only with CCMP CIPHER 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: TKIP is not used to encrypt TDLS link. 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Regardless of the cipher used on the AP connection, select CCMP 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * here. 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for " 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "testing"); 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Number of PMKIDs */ 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_i) - 2; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = pos - peer->rsnie_i; 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsnie: 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (tdls_testing & TDLS_TESTING_LONG_FRAME)) 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += sizeof(struct wpa_tdls_lnkid); 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(peer->inonce, WPA_NONCE_LEN)) { 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS: Failed to get random data for initiator Nonce"); 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->inonce, WPA_NONCE_LEN); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1", 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(struct wpa_tdls_ftie)); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = TPK_LIFETIME; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) { 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK " 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 301; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) { 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK " 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 0xffffffff; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), peer->lifetime); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) { 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in " 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Link Identifier"); 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, l); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l->bssid[5] ^= 0x01; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(*l); 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK " 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake Message 1 (peer " MACSTR ")", 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1152d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 1153df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1, 0, 0, rbuf, pos - rbuf); 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1156d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 1170d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: ftie->mic_control to set 2-RESPONSE */ 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2", 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(*ftie)); 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) { 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in response"); 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator", 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p, 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 123421de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 123521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_MIC) { 123621de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC"); 123721de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt ftie->mic[0] ^= 0x01; 123821de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt } 123921de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 1242d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, 1243df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dtoken, 0, 0, rbuf, pos - rbuf); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1246d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1260d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt int status; 1261df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt u32 peer_capab = 0; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /*TODO: ftie->mic_control to set 3-CONFIRM */ 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) { 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in confirm"); 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p, 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 132321de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 132421de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_MIC) { 132521de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC"); 132621de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt ftie->mic[0] ^= 0x01; 132721de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt } 132821de214b4ba4271ca20843f3b8fba9f1501b2a89Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1330b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidtskip_ies: 1331b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 1332df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (peer->vht_capabilities) 1333df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_VHT; 1334b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt if (peer->ht_capabilities) 1335df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_HT; 1336b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt if (peer->wmm_capable) 1337df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer_capab |= TDLS_PEER_WMM; 1338df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1339d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, 1340df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dtoken, 0, peer_capab, rbuf, pos - rbuf); 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1343d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return status; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_tdls_send_discovery_response(struct wpa_sm *sm, 13481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer, 13491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token) 13501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 13511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response " 13521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(peer " MACSTR ")", MAC2STR(peer->addr)); 13531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE, 1355df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dialog_token, 0, 0, NULL, 0); 13561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int 13601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtwpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr, 13611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *buf, size_t len) 13621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 13631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_eapol_ie_parse kde; 13641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct wpa_tdls_lnkid *lnkid; 13651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer; 13661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t min_req_len = sizeof(struct wpa_tdls_frame) + 13671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid); 13681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 dialog_token; 13691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR, 13711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MAC2STR(addr)); 13721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (len < min_req_len) { 13741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: " 13751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "%d", (int) len); 13761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 13771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dialog_token = buf[sizeof(struct wpa_tdls_frame)]; 13801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1, 13821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len - (sizeof(struct wpa_tdls_frame) + 1), 13831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &kde) < 0) 13841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 13851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!kde.lnkid) { 13871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery " 13881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Request"); 13891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 13901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid; 13931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 13951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different " 13961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt " BSS " MACSTR, MAC2STR(lnkid->bssid)); 13971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 13981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14004b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, addr, NULL); 14011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (peer == NULL) 14021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 14031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_tdls_send_discovery_response(sm, peer, dialog_token); 14051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 14061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr) 14091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 14101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 14111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 14121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer " 14141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt MACSTR, MAC2STR(addr)); 14151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST, 1416df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1, 0, 0, NULL, 0); 14171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 14181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int copy_supp_rates(const struct wpa_eapol_ie_parse *kde, 14211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_tdls_peer *peer) 14221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 14231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!kde->supp_rates) { 14241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported rates received"); 14251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 14261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1427a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peer->supp_rates_len = merge_byte_arrays( 1428a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt peer->supp_rates, sizeof(peer->supp_rates), 1429a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt kde->supp_rates + 2, kde->supp_rates_len - 2, 143034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL, 143134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt kde->ext_supp_rates_len - 2); 14321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 14331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 14341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 14351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1436f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde, 1437f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_tdls_peer *peer) 1438f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 1439f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!kde->ht_capabilities || 1440f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt kde->ht_capabilities_len < 1441f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sizeof(struct ieee80211_ht_capabilities) ) { 1442f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities " 1443f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "received"); 1444f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1445f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1446f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1447f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!peer->ht_capabilities) { 1448f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ht_capabilities = 1449f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_zalloc(sizeof(struct ieee80211_ht_capabilities)); 1450f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (peer->ht_capabilities == NULL) 1451f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1452f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1453f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1454f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(peer->ht_capabilities, kde->ht_capabilities, 1455f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sizeof(struct ieee80211_ht_capabilities)); 1456f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities", 1457f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt (u8 *) peer->ht_capabilities, 1458f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt sizeof(struct ieee80211_ht_capabilities)); 1459f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1460f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1461f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 1462f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1463f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 146433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidtstatic int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde, 146533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt struct wpa_tdls_peer *peer) 146633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt{ 146733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (!kde->vht_capabilities || 146833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt kde->vht_capabilities_len < 146933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt sizeof(struct ieee80211_vht_capabilities) ) { 147033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities " 147133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt "received"); 147233e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return 0; 147333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt } 147433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 147533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (!peer->vht_capabilities) { 147633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt peer->vht_capabilities = 147733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_zalloc(sizeof(struct ieee80211_vht_capabilities)); 147833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (peer->vht_capabilities == NULL) 147933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return -1; 148033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt } 148133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 148233e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt os_memcpy(peer->vht_capabilities, kde->vht_capabilities, 148333e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt sizeof(struct ieee80211_vht_capabilities)); 148433e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities", 148533e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt (u8 *) peer->vht_capabilities, 148633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt sizeof(struct ieee80211_vht_capabilities)); 148733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 148833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt return 0; 148933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt} 149033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 149133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 1492f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde, 1493f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_tdls_peer *peer) 1494f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 1495f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!kde->ext_capab) { 1496f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities " 1497f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt "received"); 1498f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1499f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1500f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1501f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) { 1502f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* Need to allocate buffer to fit the new information */ 1503f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_free(peer->ext_capab); 1504f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab = os_zalloc(kde->ext_capab_len - 2); 1505f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (peer->ext_capab == NULL) 1506f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return -1; 1507f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 1508f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1509f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->ext_capab_len = kde->ext_capab_len - 2; 1510f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len); 1511f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1512f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return 0; 1513f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 1514f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1515f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1516b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtstatic int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde, 1517b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt struct wpa_tdls_peer *peer) 1518b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 1519b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt struct wmm_information_element *wmm; 1520b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1521b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!kde->wmm) { 1522b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received"); 1523b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return 0; 1524b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 1525b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1526b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (kde->wmm_len < sizeof(struct wmm_information_element)) { 1527b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received"); 1528b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return -1; 1529b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt } 1530b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1531b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wmm = (struct wmm_information_element *) kde->wmm; 1532b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt peer->qos_info = wmm->qos_info; 1533b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1534df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt peer->wmm_capable = 1; 1535df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 1536b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info); 1537b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return 0; 1538b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 1539b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1540b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 1541344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde, 1542344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt struct wpa_tdls_peer *peer) 1543344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{ 1544344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!kde->supp_channels) { 1545344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported channels received"); 1546344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1547344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1548344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1549344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!peer->supp_channels || 1550344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len < kde->supp_channels_len) { 1551344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_channels); 1552344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels = os_zalloc(kde->supp_channels_len); 1553344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (peer->supp_channels == NULL) 1554344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return -1; 1555344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1556344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1557344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len = kde->supp_channels_len; 1558344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1559344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_memcpy(peer->supp_channels, kde->supp_channels, 1560344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len); 1561344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels", 1562344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt (u8 *) peer->supp_channels, peer->supp_channels_len); 1563344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1564344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt} 1565344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1566344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1567344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidtstatic int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde, 1568344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt struct wpa_tdls_peer *peer) 1569344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt{ 1570344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!kde->supp_oper_classes) { 1571344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received"); 1572344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1573344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1574344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1575344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (!peer->supp_oper_classes || 1576344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len < kde->supp_oper_classes_len) { 1577344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_free(peer->supp_oper_classes); 1578344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len); 1579344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (peer->supp_oper_classes == NULL) 1580344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return -1; 1581344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 1582344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1583344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len = kde->supp_oper_classes_len; 1584344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes, 1585344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len); 1586344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes", 1587344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt (u8 *) peer->supp_oper_classes, 1588344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len); 1589344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 1590344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt} 1591344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1592344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie = NULL; 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = 0; 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_ver; 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ielen; 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 16151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int existing_peer = 0; 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = buf; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* driver had already verified the frame format */ 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *cpos++; /* dialog token */ 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken); 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer); 16294b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 16304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt goto error; 16311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 16320ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt /* If found, use existing entry instead of adding a new one; 16330ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * how to handle the case where both ends initiate at the 16340ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * same time? */ 16350ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (existing_peer) { 16360ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (peer->tpk_success) { 16370ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while " 16380ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "direct link is enabled - tear down the " 16390ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "old link first"); 16408b43e82b5aa16d167d3e2696b7827c412b0e0a00Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 16410ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 16420ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt 16430ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt /* 16440ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * An entry is already present, so check if we already sent a 16450ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * TDLS Setup Request. If so, compare MAC addresses and let the 16460ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * STA with the lower MAC address continue as the initiator. 16470ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * The other negotiation is terminated. 16480ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt */ 16490ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (peer->initiator) { 16500ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) { 16510ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard request " 16520ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "from peer with higher address " 16530ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MACSTR, MAC2STR(src_addr)); 16540ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt return -1; 16550ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } else { 16560ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Accept request " 16570ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "from peer with lower address " 16580ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MACSTR " (terminate previously " 16590ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "initiated negotiation", 16600ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt MAC2STR(src_addr)); 16618b43e82b5aa16d167d3e2696b7827c412b0e0a00Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 16620ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 16630ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 16640ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 16650ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt 16661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* capability information */ 16671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->capability = WPA_GET_LE16(cpos); 16681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cpos += 2; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (cpos - buf); /* start of IE in buf */ 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) { 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1"); 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1", 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS"); 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_NOT_IN_SAME_BSS; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR, 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (copy_supp_rates(&kde, peer) < 0) 16941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 16951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1696f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ht_capab(&kde, peer) < 0) 1697f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 1698f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 169933e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (copy_peer_vht_capab(&kde, peer) < 0) 170033e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt goto error; 170133e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 1702f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ext_capab(&kde, peer) < 0) 1703f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 1704f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1705344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_channels(&kde, peer) < 0) 1706344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 1707344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1708344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_oper_classes(&kde, peer) < 0) 1709344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 1710344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 1711f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->qos_info = kde.qosinfo; 1712f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1713b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt /* Overwrite with the qos_info obtained in WMM IE */ 1714b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (copy_peer_wmm_capab(&kde, peer) < 0) 1715b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt goto error; 1716b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 171751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt peer->aid = kde.aid; 171851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { 17214b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, src_addr, NULL); 17224b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 17234b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt goto error; 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of " 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS setup - send own request"); 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_tpk_m1(sm, peer); 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS"); 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while " 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "security is disabled"); 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_SECURITY_DISABLED; 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1"); 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in " 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1"); 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1"); 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie.capabilities & 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) != 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_CAPABILITY_PEERKEY_ENABLED) { 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in " 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSN_IE_CAPAB; 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1"); 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime); 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime < 300) { 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime"); 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 18091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TDLS_TESTING 18101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { 18111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) { 18121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 18131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The request frame from us is going to win, so do not 18141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * replace information based on this request frame from 18151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the peer. 18161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 18171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto skip_rsn_check; 18181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 18201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 18211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; /* Need to check */ 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn_check; 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = kde.rsn_ie_len; 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18376102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) { 18386102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt /* 18396102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * There is no point in updating the RNonce for every obtained 18406102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * TPK M1 frame (e.g., retransmission due to timeout) with the 18416102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * same INonce (SNonce in FTIE). However, if the TPK M1 is 18426102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * retransmitted with a different INonce, update the RNonce 18436102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt * since this is for a new TDLS session. 18446102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt */ 18456102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt wpa_printf(MSG_DEBUG, 18466102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt "TDLS: New TPK M1 INonce - generate new RNonce"); 18476102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN); 18486102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) { 18496102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt wpa_msg(sm->ctx->ctx, MSG_WARNING, 18506102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt "TDLS: Failed to get random data for responder nonce"); 18516102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt goto error; 18526102472da23e48cb1406b87ec767f4fd9a40a85dSunil Dutt } 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* get version info from RSNIE received from Peer */ 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) kde.rsn_ie; 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = WPA_GET_LE16(hdr->version); 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* use min(peer's version, out version) */ 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ver > RSN_VERSION) 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = RSN_VERSION; 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_p; 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, rsn_ver); 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_p) - 2; 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = pos - peer->rsnie_p; 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* temp fix: validation of RSNIE later */ 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len); 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = peer->rsnie_i_len; 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, peer->rsnie_p_len); 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = lifetime; 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn_check: 19051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* add the peer to the driver as a "setup in progress" peer */ 190643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, 190743cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt NULL, 0, NULL, 0, NULL, 0, NULL, 0)) 190843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt goto error; 190943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt 191073b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 1; 19111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); 19131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) { 1914d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 19151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 19161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 192343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (peer) 192443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt wpa_tdls_peer_free(sm, peer); 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19298da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidtstatic int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_success = 1; 193273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 0; 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = peer->lifetime; 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Start the initiator process a bit earlier to avoid race 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * condition with the responder sending teardown request. 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 3 && peer->initiator) 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime -= 3; 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout, 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peer); 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) { 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK " 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expiration"); 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1953f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt /* add supported rates, capabilities, and qos_info to the TDLS peer */ 195451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid, 195551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt peer->capability, 19568da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->supp_rates, peer->supp_rates_len, 19578da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->ht_capabilities, 19588da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->vht_capabilities, 19598da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->qos_info, peer->ext_capab, 1960344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->ext_capab_len, 1961344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels, 1962344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_channels_len, 1963344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes, 1964344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt peer->supp_oper_classes_len) < 0) 19658da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return -1; 19661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19678da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) { 19688da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Could not configure key to the " 19698da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "driver"); 19708da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return -1; 19718da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 19728da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 0; 19738da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt 19748da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1993292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt int ret = 0; 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 " 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2: " MACSTR, MAC2STR(src_addr)); 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20060ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (!peer->initiator) { 20070ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt /* 20080ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * This may happen if both devices try to initiate TDLS at the 20090ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * same time and we accept the TPK M1 from the peer in 20100ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt * wpa_tdls_process_tpk_m1() and clear our previous state. 20110ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt */ 20120ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so " 20130ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt "ignore TPK M2 from " MACSTR, MAC2STR(src_addr)); 20140ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt return -1; 20150ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST); 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt if (len < 3 + 2 + 1) { 2019d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2021adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt } 2022adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */; 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != WLAN_STATUS_SUCCESS) { 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u", 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2031d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNSPECIFIED_FAILURE; 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: need to verify dialog token matches here or in kernel */ 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *pos++; /* dialog token */ 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken); 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2042adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt if (len < 3 + 2 + 1 + 2) { 2043d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2045adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt } 20461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* capability information */ 20481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt peer->capability = WPA_GET_LE16(pos); 20491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2; 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) { 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2"); 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DECLINE_RESP) { 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response"); 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2"); 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2", 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS"); 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_NOT_IN_SAME_BSS; 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (copy_supp_rates(&kde, peer) < 0) 20811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto error; 20821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2083f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ht_capab(&kde, peer) < 0) 2084f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 2085f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 208633e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt if (copy_peer_vht_capab(&kde, peer) < 0) 208733e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt goto error; 208833e38bfa7159cef089d6ee0d904778e184c72c47Dmitry Shmidt 2089f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (copy_peer_ext_capab(&kde, peer) < 0) 2090f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt goto error; 2091f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2092344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_channels(&kde, peer) < 0) 2093344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 2094344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 2095344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (copy_peer_supp_oper_classes(&kde, peer) < 0) 2096344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt goto error; 2097344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 2098f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer->qos_info = kde.qosinfo; 2099f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2100b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt /* Overwrite with the qos_info obtained in WMM IE */ 2101b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (copy_peer_wmm_capab(&kde, peer) < 0) 2102b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt goto error; 2103b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 210451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt peer->aid = kde.aid; 210551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2"); 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 212109f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { 212209f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt wpa_printf(MSG_INFO, 212309f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt "TDLS: Too long Responder RSN IE in TPK M2"); 212409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 212509f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt goto error; 212609f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt } 212709f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: bitwise comparison of RSN IE is not the correct way of 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validation this. It can be different, but certain fields must 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * match. Since we list only a single pairwise cipher in TPK M1, the 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * memcmp is likely to work in most cases, though. 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_i_len || 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) { 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does " 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with RSN IE used in TPK M1"); 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1", 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2"); 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) { 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2"); 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2", 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does " 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE SNonce used in TPK M1"); 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Silently discard the frame */ 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Responder Nonce and RSN IE */ 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN); 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len); 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = kde.rsn_ie_len; 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2"); 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2", 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2 (expected %u)", lifetime, peer->lifetime); 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TPK M2 is right */ 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid, 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Discard the frame */ 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 220338ffd8879e7990491033bf20568212e8c3472b48Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22078da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (wpa_tdls_set_key(sm, peer) < 0) { 22088da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt /* 22098da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * Some drivers may not be able to config the key prior to full 22108da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * STA entry having been configured. 22118da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt */ 22128da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " 22138da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "STA entry is complete"); 22148da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 1; 22158da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / " 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK Handshake Message 3"); 2222d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0) { 2223d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 2224d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt return -1; 2225d5c075b0c218277d0f926daf1f9eff974b9656dcDmitry Shmidt } 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2227292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (!peer->tpk_success) { 2228292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt /* 2229292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * Enable Link only when tpk_success is 0, signifying that this 2230292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * processing of TPK M2 frame is not because of a retransmission 2231292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * during TDLS setup handshake. 2232292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt */ 2233292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt ret = wpa_tdls_enable_link(sm, peer); 2234292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (ret < 0) { 2235292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not enable link"); 2236292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_tdls_do_teardown( 2237292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt sm, peer, 2238292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2239292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt } 22408da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 22418da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return ret; 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2246d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 2263292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt int ret = 0; 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 " 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3: " MACSTR, MAC2STR(src_addr)); 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE); 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 2279adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != 0) { 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u", 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 2288adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */ + 1 /* dialog token */; 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3"); 2295adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3"); 2300adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3", 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) kde.lnkid, kde.lnkid_len); 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS"); 2308adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3"); 2316adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3", 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL) { 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3"); 2324adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3", 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_p_len || 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) { 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match " 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the one sent in TPK M2"); 2332adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) { 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does " 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE ANonce used in TPK M2"); 2338adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not " 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with FTIE SNonce used in TPK M1"); 2344adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3"); 2349adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3", 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, sizeof(*timeoutie)); 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3", 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3 (expected %u)", lifetime, peer->lifetime); 2360adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid, 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 2366adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt goto error; 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23698da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt if (wpa_tdls_set_key(sm, peer) < 0) { 23708da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt /* 23718da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * Some drivers may not be able to config the key prior to full 23728da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt * STA entry having been configured. 23738da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt */ 23748da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " 23758da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt "STA entry is complete"); 23768da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt peer->reconfig_key = 1; 23778da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 2380292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (!peer->tpk_success) { 2381292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt /* 2382292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * Enable Link only when tpk_success is 0, signifying that this 2383292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * processing of TPK M3 frame is not because of a retransmission 2384292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt * during TDLS setup handshake. 2385292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt */ 2386292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt ret = wpa_tdls_enable_link(sm, peer); 2387292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt if (ret < 0) { 2388292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Could not enable link"); 2389292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt wpa_tdls_do_teardown( 2390292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt sm, peer, 2391292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2392292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt } 23938da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 23948da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt return ret; 2395adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutterror: 2396d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 2397adce9cf73c2237aff40a49fc3d0b315711f291d8Sunil Dutt return -1; 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs) 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie; 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(lifetime, 0, ie_len); 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL; 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2; 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME; 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(lifetime->value, tsecs); 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1) 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send TPK Handshake Message 1 info to driver to start TDLS 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - " 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reject request to start setup"); 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 24458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24474b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt peer = wpa_tdls_add_peer(sm, addr, NULL); 24484b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt if (peer == NULL) 24494b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return -1; 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 245173b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt if (peer->tpk_in_progress) { 245273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer"); 245373b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt return 0; 245473b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt } 245573b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt 24568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 24578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* add the peer to the driver as a "setup in progress" peer */ 245951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, 2460344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt NULL, 0, NULL, 0, NULL, 0); 24611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 246273b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt peer->tpk_in_progress = 1; 246373b28cc4bd1d5efa3534ad9e28365fea9a62ffd3Sunil Dutt 24641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { 2465d0ef38b52c069e34102b38dafbbc1fe055364ae8Sunil Dutt wpa_tdls_disable_peer_link(sm, peer); 24661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 24671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24734b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtvoid wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr) 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) 24784b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL || !peer->tpk_success) 24864b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt return; 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_external_setup) { 24891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 24901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Disable previous link to allow renegotiation to be completed 24911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * on AP path. 24921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 2493b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt wpa_tdls_do_teardown(sm, peer, 2494b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 24951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_rx_tdls - Receive TDLS data frame 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to receive TDLS (ethertype = 0x890d) data frames. 25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr, 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_frame *tf; 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation", 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (sm->tdls_disabled || !sm->tdls_supported) { 25141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled " 25151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "or unsupported by driver"); 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) { 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message"); 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*tf)) { 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Drop too short frame"); 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check to make sure its a valid encapsulated TDLS frame */ 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf = (struct wpa_tdls_frame *) buf; 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tf->payloadtype != 2 /* TDLS_RFTYPE */ || 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->category != WLAN_ACTION_TDLS) { 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u " 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "category=%u action=%u", 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->payloadtype, tf->category, tf->action); 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tf->action) { 25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_REQUEST: 25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m1(sm, src_addr, buf, len); 25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_RESPONSE: 25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m2(sm, src_addr, buf, len); 25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_CONFIRM: 25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m3(sm, src_addr, buf, len); 25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_TEARDOWN: 25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_recv_teardown(sm, src_addr, buf, len); 25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_TDLS_DISCOVERY_REQUEST: 25531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_tdls_process_discovery_request(sm, src_addr, buf, len); 25541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Kernel code will process remaining frames */ 25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u", 25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->action); 25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_init - Initialize driver interface parameters for TDLS 25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to initialize driver interface parameters for TDLS. 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_drv_init() must have been called before this function to initialize the 25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver interface. 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_init(struct wpa_sm *sm) 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 257804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname : 257904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->ifname, 258004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->own_addr, 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls, 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, 0); 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls == NULL) { 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet " 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection"); 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 25901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Drivers that support TDLS but don't implement the get_capa callback 25911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * are assumed to perform everything internally 25921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 25931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported, 25941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &sm->tdls_external_setup) < 0) { 25951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_supported = 1; 25961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_external_setup = 0; 25971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by " 26001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "driver", sm->tdls_supported ? "" : " not"); 26011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup", 26021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt sm->tdls_external_setup ? "external" : "internal"); 26031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtvoid wpa_tdls_teardown_peers(struct wpa_sm *sm) 2609f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 2610f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpa_tdls_peer *peer; 2611f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2612f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer = sm->tdls; 2613f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2614f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Tear down peers"); 2615f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2616f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt while (peer) { 2617f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR, 2618f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt MAC2STR(peer->addr)); 2619f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (sm->tdls_external_setup) 2620b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt wpa_tdls_do_teardown(sm, peer, 2621b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 2622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt else 2623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); 2624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt peer = peer->next; 2626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 2627f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 2628f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 2629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_remove_peers(struct wpa_sm *sm) 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, *tmp; 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = sm->tdls; 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls = NULL; 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peer) { 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = peer->next; 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)", 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr), res); 26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer); 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = tmp; 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to recover driver interface parameters for TDLS 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and frees resources allocated for it. 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_deinit(struct wpa_sm *sm) 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls) 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_tdls); 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_tdls = NULL; 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc(struct wpa_sm *sm) 26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association"); 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_disassoc(struct wpa_sm *sm) 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation"); 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_prohibited(const u8 *ies, size_t len) 26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse elems; 26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ies == NULL) 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(ies, len, &elems) < 0) 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5) 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* bit 38 - TDLS Prohibited */ 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return !!(elems.ext_capab[2 + 4] & 0x40); 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited = wpa_tdls_prohibited(ies, len); 27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS", 27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited ? "prohibited" : "allowed"); 27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) { 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on " 27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Re)Association Response IEs"); 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited = 1; 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_enable(struct wpa_sm *sm, int enabled) 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled"); 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_disabled = !enabled; 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 27261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_tdls_is_external_setup(struct wpa_sm *sm) 27271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 27281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return sm->tdls_external_setup; 27291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2730