LCOV - code coverage report
Current view: top level - src/rsn_supp - tdls.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 1099 1395 78.8 %
Date: 2015-09-27 Functions: 61 63 96.8 %

          Line data    Source code
       1             : /*
       2             :  * wpa_supplicant - TDLS
       3             :  * Copyright (c) 2010-2011, Atheros Communications
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "utils/includes.h"
      10             : 
      11             : #include "utils/common.h"
      12             : #include "utils/eloop.h"
      13             : #include "utils/os.h"
      14             : #include "common/ieee802_11_defs.h"
      15             : #include "common/ieee802_11_common.h"
      16             : #include "crypto/sha256.h"
      17             : #include "crypto/crypto.h"
      18             : #include "crypto/aes_wrap.h"
      19             : #include "rsn_supp/wpa.h"
      20             : #include "rsn_supp/wpa_ie.h"
      21             : #include "rsn_supp/wpa_i.h"
      22             : #include "drivers/driver.h"
      23             : #include "l2_packet/l2_packet.h"
      24             : 
      25             : #ifdef CONFIG_TDLS_TESTING
      26             : #define TDLS_TESTING_LONG_FRAME BIT(0)
      27             : #define TDLS_TESTING_ALT_RSN_IE BIT(1)
      28             : #define TDLS_TESTING_DIFF_BSSID BIT(2)
      29             : #define TDLS_TESTING_SHORT_LIFETIME BIT(3)
      30             : #define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4)
      31             : #define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5)
      32             : #define TDLS_TESTING_LONG_LIFETIME BIT(6)
      33             : #define TDLS_TESTING_CONCURRENT_INIT BIT(7)
      34             : #define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8)
      35             : #define TDLS_TESTING_DECLINE_RESP BIT(9)
      36             : #define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10)
      37             : #define TDLS_TESTING_WRONG_MIC BIT(11)
      38             : unsigned int tdls_testing = 0;
      39             : #endif /* CONFIG_TDLS_TESTING */
      40             : 
      41             : #define TPK_LIFETIME 43200 /* 12 hours */
      42             : #define TPK_M1_RETRY_COUNT 3
      43             : #define TPK_M1_TIMEOUT 5000 /* in milliseconds */
      44             : #define TPK_M2_RETRY_COUNT 10
      45             : #define TPK_M2_TIMEOUT 500 /* in milliseconds */
      46             : 
      47             : #define TDLS_MIC_LEN            16
      48             : 
      49             : #define TDLS_TIMEOUT_LEN        4
      50             : 
      51             : struct wpa_tdls_ftie {
      52             :         u8 ie_type; /* FTIE */
      53             :         u8 ie_len;
      54             :         u8 mic_ctrl[2];
      55             :         u8 mic[TDLS_MIC_LEN];
      56             :         u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */
      57             :         u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */
      58             :         /* followed by optional elements */
      59             : } STRUCT_PACKED;
      60             : 
      61             : struct wpa_tdls_timeoutie {
      62             :         u8 ie_type; /* Timeout IE */
      63             :         u8 ie_len;
      64             :         u8 interval_type;
      65             :         u8 value[TDLS_TIMEOUT_LEN];
      66             : } STRUCT_PACKED;
      67             : 
      68             : struct wpa_tdls_lnkid {
      69             :         u8 ie_type; /* Link Identifier IE */
      70             :         u8 ie_len;
      71             :         u8 bssid[ETH_ALEN];
      72             :         u8 init_sta[ETH_ALEN];
      73             :         u8 resp_sta[ETH_ALEN];
      74             : } STRUCT_PACKED;
      75             : 
      76             : /* TDLS frame headers as per IEEE Std 802.11z-2010 */
      77             : struct wpa_tdls_frame {
      78             :         u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */
      79             :         u8 category; /* Category */
      80             :         u8 action; /* Action (enum tdls_frame_type) */
      81             : } STRUCT_PACKED;
      82             : 
      83             : static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs);
      84             : static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx);
      85             : static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
      86             : static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
      87             :                                        struct wpa_tdls_peer *peer);
      88             : static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
      89             :                                   u16 reason_code);
      90             : 
      91             : 
      92             : #define TDLS_MAX_IE_LEN 80
      93             : #define IEEE80211_MAX_SUPP_RATES 32
      94             : 
      95             : struct wpa_tdls_peer {
      96             :         struct wpa_tdls_peer *next;
      97             :         unsigned int reconfig_key:1;
      98             :         int initiator; /* whether this end was initiator for TDLS setup */
      99             :         u8 addr[ETH_ALEN]; /* other end MAC address */
     100             :         u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
     101             :         u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */
     102             :         u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */
     103             :         size_t rsnie_i_len;
     104             :         u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */
     105             :         size_t rsnie_p_len;
     106             :         u32 lifetime;
     107             :         int cipher; /* Selected cipher (WPA_CIPHER_*) */
     108             :         u8 dtoken;
     109             : 
     110             :         struct tpk {
     111             :                 u8 kck[16]; /* TPK-KCK */
     112             :                 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
     113             :         } tpk;
     114             :         int tpk_set;
     115             :         int tpk_success;
     116             :         int tpk_in_progress;
     117             : 
     118             :         struct tpk_timer {
     119             :                 u8 dest[ETH_ALEN];
     120             :                 int count;      /* Retry Count */
     121             :                 int timer;      /* Timeout in milliseconds */
     122             :                 u8 action_code; /* TDLS frame type */
     123             :                 u8 dialog_token;
     124             :                 u16 status_code;
     125             :                 u32 peer_capab;
     126             :                 int buf_len;    /* length of TPK message for retransmission */
     127             :                 u8 *buf;        /* buffer for TPK message */
     128             :         } sm_tmr;
     129             : 
     130             :         u16 capability;
     131             : 
     132             :         u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
     133             :         size_t supp_rates_len;
     134             : 
     135             :         struct ieee80211_ht_capabilities *ht_capabilities;
     136             :         struct ieee80211_vht_capabilities *vht_capabilities;
     137             : 
     138             :         u8 qos_info;
     139             : 
     140             :         u16 aid;
     141             : 
     142             :         u8 *ext_capab;
     143             :         size_t ext_capab_len;
     144             : 
     145             :         u8 *supp_channels;
     146             :         size_t supp_channels_len;
     147             : 
     148             :         u8 *supp_oper_classes;
     149             :         size_t supp_oper_classes_len;
     150             : 
     151             :         u8 wmm_capable;
     152             : 
     153             :         /* channel switch currently enabled */
     154             :         int chan_switch_enabled;
     155             : };
     156             : 
     157             : 
     158         498 : static int wpa_tdls_get_privacy(struct wpa_sm *sm)
     159             : {
     160             :         /*
     161             :          * Get info needed from supplicant to check if the current BSS supports
     162             :          * security. Other than OPEN mode, rest are considered secured
     163             :          * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
     164             :          */
     165         498 :         return sm->pairwise_cipher != WPA_CIPHER_NONE;
     166             : }
     167             : 
     168             : 
     169          71 : static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
     170             : {
     171          71 :         os_memcpy(pos, ie, ie_len);
     172          71 :         return pos + ie_len;
     173             : }
     174             : 
     175             : 
     176           2 : static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
     177             : {
     178           2 :         if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
     179             :                            0, 0, NULL, 0, NULL, 0) < 0) {
     180           0 :                 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
     181             :                            "the driver");
     182           0 :                 return -1;
     183             :         }
     184             : 
     185           2 :         return 0;
     186             : }
     187             : 
     188             : 
     189          78 : static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
     190             : {
     191             :         u8 key_len;
     192             :         u8 rsc[6];
     193             :         enum wpa_alg alg;
     194             : 
     195          78 :         os_memset(rsc, 0, 6);
     196             : 
     197          78 :         switch (peer->cipher) {
     198             :         case WPA_CIPHER_CCMP:
     199          78 :                 alg = WPA_ALG_CCMP;
     200          78 :                 key_len = 16;
     201          78 :                 break;
     202             :         case WPA_CIPHER_NONE:
     203           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
     204             :                            "NONE - do not use pairwise keys");
     205           0 :                 return -1;
     206             :         default:
     207           0 :                 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
     208             :                            sm->pairwise_cipher);
     209           0 :                 return -1;
     210             :         }
     211             : 
     212         156 :         if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
     213          78 :                            rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
     214          39 :                 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
     215             :                            "driver");
     216          39 :                 return -1;
     217             :         }
     218          39 :         return 0;
     219             : }
     220             : 
     221             : 
     222         132 : static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
     223             :                                  u8 action_code, u8 dialog_token,
     224             :                                  u16 status_code, u32 peer_capab,
     225             :                                  int initiator, const u8 *buf, size_t len)
     226             : {
     227         132 :         return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
     228             :                                      status_code, peer_capab, initiator, buf,
     229             :                                      len);
     230             : }
     231             : 
     232             : 
     233         127 : static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
     234             :                              u8 dialog_token, u16 status_code, u32 peer_capab,
     235             :                              int initiator, const u8 *msg, size_t msg_len)
     236             : {
     237             :         struct wpa_tdls_peer *peer;
     238             : 
     239         889 :         wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
     240             :                    "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
     241             :                    "msg_len=%u",
     242         762 :                    MAC2STR(dest), action_code, dialog_token, status_code,
     243             :                    peer_capab, initiator, (unsigned int) msg_len);
     244             : 
     245         127 :         if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
     246             :                                   status_code, peer_capab, initiator, msg,
     247             :                                   msg_len)) {
     248           1 :                 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
     249             :                            "(action_code=%u)", action_code);
     250           1 :                 return -1;
     251             :         }
     252             : 
     253         126 :         if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
     254          67 :             action_code == WLAN_TDLS_TEARDOWN ||
     255          65 :             action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
     256             :             action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
     257          63 :                 return 0; /* No retries */
     258             : 
     259          63 :         for (peer = sm->tdls; peer; peer = peer->next) {
     260          63 :                 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
     261          63 :                         break;
     262             :         }
     263             : 
     264          63 :         if (peer == NULL) {
     265           0 :                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
     266           0 :                            "retry " MACSTR, MAC2STR(dest));
     267           0 :                 return 0;
     268             :         }
     269             : 
     270          63 :         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
     271             : 
     272          63 :         if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
     273          31 :                 peer->sm_tmr.count = TPK_M2_RETRY_COUNT;
     274          31 :                 peer->sm_tmr.timer = TPK_M2_TIMEOUT;
     275             :         } else {
     276          32 :                 peer->sm_tmr.count = TPK_M1_RETRY_COUNT;
     277          32 :                 peer->sm_tmr.timer = TPK_M1_TIMEOUT;
     278             :         }
     279             : 
     280             :         /* Copy message to resend on timeout */
     281          63 :         os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
     282          63 :         peer->sm_tmr.action_code = action_code;
     283          63 :         peer->sm_tmr.dialog_token = dialog_token;
     284          63 :         peer->sm_tmr.status_code = status_code;
     285          63 :         peer->sm_tmr.peer_capab = peer_capab;
     286          63 :         peer->sm_tmr.buf_len = msg_len;
     287          63 :         os_free(peer->sm_tmr.buf);
     288          63 :         peer->sm_tmr.buf = os_malloc(msg_len);
     289          63 :         if (peer->sm_tmr.buf == NULL)
     290           0 :                 return -1;
     291          63 :         os_memcpy(peer->sm_tmr.buf, msg, msg_len);
     292             : 
     293          63 :         wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
     294             :                    "(action_code=%u)", action_code);
     295          63 :         eloop_register_timeout(peer->sm_tmr.timer / 1000,
     296          63 :                                (peer->sm_tmr.timer % 1000) * 1000,
     297             :                                wpa_tdls_tpk_retry_timeout, sm, peer);
     298          63 :         return 0;
     299             : }
     300             : 
     301             : 
     302          31 : static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
     303             :                                 u16 reason_code)
     304             : {
     305             :         int ret;
     306             : 
     307          31 :         ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
     308             :         /* disable the link after teardown was sent */
     309          31 :         wpa_tdls_disable_peer_link(sm, peer);
     310             : 
     311          31 :         return ret;
     312             : }
     313             : 
     314             : 
     315           5 : static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
     316             : {
     317             : 
     318           5 :         struct wpa_sm *sm = eloop_ctx;
     319           5 :         struct wpa_tdls_peer *peer = timeout_ctx;
     320             : 
     321           5 :         if (peer->sm_tmr.count) {
     322           5 :                 peer->sm_tmr.count--;
     323             : 
     324           5 :                 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
     325             :                            "(action_code=%u)",
     326           5 :                            peer->sm_tmr.action_code);
     327             : 
     328           5 :                 if (peer->sm_tmr.buf == NULL) {
     329           0 :                         wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
     330             :                                    "for action_code=%u",
     331           0 :                                    peer->sm_tmr.action_code);
     332           0 :                         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
     333             :                                              peer);
     334           5 :                         return;
     335             :                 }
     336             : 
     337             :                 /* resend TPK Handshake Message to Peer */
     338          25 :                 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
     339           5 :                                           peer->sm_tmr.action_code,
     340           5 :                                           peer->sm_tmr.dialog_token,
     341           5 :                                           peer->sm_tmr.status_code,
     342             :                                           peer->sm_tmr.peer_capab,
     343             :                                           peer->initiator,
     344           5 :                                           peer->sm_tmr.buf,
     345           5 :                                           peer->sm_tmr.buf_len)) {
     346           0 :                         wpa_printf(MSG_INFO, "TDLS: Failed to retry "
     347             :                                    "transmission");
     348             :                 }
     349             : 
     350           5 :                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
     351           5 :                 eloop_register_timeout(peer->sm_tmr.timer / 1000,
     352           5 :                                        (peer->sm_tmr.timer % 1000) * 1000,
     353             :                                        wpa_tdls_tpk_retry_timeout, sm, peer);
     354             :         } else {
     355           0 :                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
     356             : 
     357           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
     358           0 :                 wpa_tdls_do_teardown(sm, peer,
     359             :                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
     360             :         }
     361             : }
     362             : 
     363             : 
     364          58 : static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
     365             :                                               struct wpa_tdls_peer *peer,
     366             :                                               u8 action_code)
     367             : {
     368          58 :         if (action_code == peer->sm_tmr.action_code) {
     369          57 :                 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
     370             :                            "action_code=%u", action_code);
     371             : 
     372             :                 /* Cancel Timeout registered */
     373          57 :                 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
     374             : 
     375             :                 /* free all resources meant for retry */
     376          57 :                 os_free(peer->sm_tmr.buf);
     377          57 :                 peer->sm_tmr.buf = NULL;
     378             : 
     379          57 :                 peer->sm_tmr.count = 0;
     380          57 :                 peer->sm_tmr.timer = 0;
     381          57 :                 peer->sm_tmr.buf_len = 0;
     382          57 :                 peer->sm_tmr.action_code = 0xff;
     383             :         } else {
     384           1 :                 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
     385             :                            "(Unknown action_code=%u)", action_code);
     386             :         }
     387          58 : }
     388             : 
     389             : 
     390          44 : static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
     391             :                                   const u8 *own_addr, const u8 *bssid)
     392             : {
     393             :         u8 key_input[SHA256_MAC_LEN];
     394             :         const u8 *nonce[2];
     395             :         size_t len[2];
     396             :         u8 data[3 * ETH_ALEN];
     397             : 
     398             :         /* IEEE Std 802.11z-2010 8.5.9.1:
     399             :          * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
     400             :          */
     401          44 :         len[0] = WPA_NONCE_LEN;
     402          44 :         len[1] = WPA_NONCE_LEN;
     403          44 :         if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
     404          18 :                 nonce[0] = peer->inonce;
     405          18 :                 nonce[1] = peer->rnonce;
     406             :         } else {
     407          26 :                 nonce[0] = peer->rnonce;
     408          26 :                 nonce[1] = peer->inonce;
     409             :         }
     410          44 :         wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
     411          44 :         wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
     412          44 :         sha256_vector(2, nonce, len, key_input);
     413          44 :         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
     414             :                         key_input, SHA256_MAC_LEN);
     415             : 
     416             :         /*
     417             :          * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
     418             :          *      min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
     419             :          * TODO: is N_KEY really included in KDF Context and if so, in which
     420             :          * presentation format (little endian 16-bit?) is it used? It gets
     421             :          * added by the KDF anyway..
     422             :          */
     423             : 
     424          44 :         if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
     425          22 :                 os_memcpy(data, own_addr, ETH_ALEN);
     426          22 :                 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
     427             :         } else {
     428          22 :                 os_memcpy(data, peer->addr, ETH_ALEN);
     429          22 :                 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
     430             :         }
     431          44 :         os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
     432          44 :         wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
     433             : 
     434          44 :         sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
     435          44 :                    (u8 *) &peer->tpk, sizeof(peer->tpk));
     436          44 :         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
     437          44 :                         peer->tpk.kck, sizeof(peer->tpk.kck));
     438          44 :         wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
     439          44 :                         peer->tpk.tk, sizeof(peer->tpk.tk));
     440          44 :         peer->tpk_set = 1;
     441          44 : }
     442             : 
     443             : 
     444             : /**
     445             :  * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
     446             :  * @kck: TPK-KCK
     447             :  * @lnkid: Pointer to the beginning of Link Identifier IE
     448             :  * @rsnie: Pointer to the beginning of RSN IE used for handshake
     449             :  * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
     450             :  * @ftie: Pointer to the beginning of FT IE
     451             :  * @mic: Pointer for writing MIC
     452             :  *
     453             :  * Calculate MIC for TDLS frame.
     454             :  */
     455          85 : static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
     456             :                              const u8 *rsnie, const u8 *timeoutie,
     457             :                              const u8 *ftie, u8 *mic)
     458             : {
     459             :         u8 *buf, *pos;
     460             :         struct wpa_tdls_ftie *_ftie;
     461             :         const struct wpa_tdls_lnkid *_lnkid;
     462             :         int ret;
     463         170 :         int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
     464          85 :                 2 + timeoutie[1] + 2 + ftie[1];
     465          85 :         buf = os_zalloc(len);
     466          85 :         if (!buf) {
     467           0 :                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
     468           0 :                 return -1;
     469             :         }
     470             : 
     471          85 :         pos = buf;
     472          85 :         _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
     473             :         /* 1) TDLS initiator STA MAC address */
     474          85 :         os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
     475          85 :         pos += ETH_ALEN;
     476             :         /* 2) TDLS responder STA MAC address */
     477          85 :         os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
     478          85 :         pos += ETH_ALEN;
     479             :         /* 3) Transaction Sequence number */
     480          85 :         *pos++ = trans_seq;
     481             :         /* 4) Link Identifier IE */
     482          85 :         os_memcpy(pos, lnkid, 2 + lnkid[1]);
     483          85 :         pos += 2 + lnkid[1];
     484             :         /* 5) RSN IE */
     485          85 :         os_memcpy(pos, rsnie, 2 + rsnie[1]);
     486          85 :         pos += 2 + rsnie[1];
     487             :         /* 6) Timeout Interval IE */
     488          85 :         os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
     489          85 :         pos += 2 + timeoutie[1];
     490             :         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
     491          85 :         os_memcpy(pos, ftie, 2 + ftie[1]);
     492          85 :         _ftie = (struct wpa_tdls_ftie *) pos;
     493          85 :         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
     494          85 :         pos += 2 + ftie[1];
     495             : 
     496          85 :         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
     497          85 :         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
     498          85 :         ret = omac1_aes_128(kck, buf, pos - buf, mic);
     499          85 :         os_free(buf);
     500          85 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
     501          85 :         return ret;
     502             : }
     503             : 
     504             : 
     505             : /**
     506             :  * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
     507             :  * @kck: TPK-KCK
     508             :  * @trans_seq: Transaction Sequence Number (4 - Teardown)
     509             :  * @rcode: Reason code for Teardown
     510             :  * @dtoken: Dialog Token used for that particular link
     511             :  * @lnkid: Pointer to the beginning of Link Identifier IE
     512             :  * @ftie: Pointer to the beginning of FT IE
     513             :  * @mic: Pointer for writing MIC
     514             :  *
     515             :  * Calculate MIC for TDLS frame.
     516             :  */
     517          39 : static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
     518             :                                      u8 dtoken, const u8 *lnkid,
     519             :                                      const u8 *ftie, u8 *mic)
     520             : {
     521             :         u8 *buf, *pos;
     522             :         struct wpa_tdls_ftie *_ftie;
     523             :         int ret;
     524             :         int len;
     525             : 
     526          39 :         if (lnkid == NULL)
     527           0 :                 return -1;
     528             : 
     529          78 :         len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
     530          39 :                 sizeof(trans_seq) + 2 + ftie[1];
     531             : 
     532          39 :         buf = os_zalloc(len);
     533          39 :         if (!buf) {
     534           0 :                 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
     535           0 :                 return -1;
     536             :         }
     537             : 
     538          39 :         pos = buf;
     539             :         /* 1) Link Identifier IE */
     540          39 :         os_memcpy(pos, lnkid, 2 + lnkid[1]);
     541          39 :         pos += 2 + lnkid[1];
     542             :         /* 2) Reason Code */
     543          39 :         WPA_PUT_LE16(pos, rcode);
     544          39 :         pos += sizeof(rcode);
     545             :         /* 3) Dialog token */
     546          39 :         *pos++ = dtoken;
     547             :         /* 4) Transaction Sequence number */
     548          39 :         *pos++ = trans_seq;
     549             :         /* 7) FTIE, with the MIC field of the FTIE set to 0 */
     550          39 :         os_memcpy(pos, ftie, 2 + ftie[1]);
     551          39 :         _ftie = (struct wpa_tdls_ftie *) pos;
     552          39 :         os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
     553          39 :         pos += 2 + ftie[1];
     554             : 
     555          39 :         wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
     556          39 :         wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
     557          39 :         ret = omac1_aes_128(kck, buf, pos - buf, mic);
     558          39 :         os_free(buf);
     559          39 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
     560          39 :         return ret;
     561             : }
     562             : 
     563             : 
     564          41 : static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
     565             :                                           struct wpa_tdls_peer *peer,
     566             :                                           const u8 *lnkid, const u8 *timeoutie,
     567             :                                           const struct wpa_tdls_ftie *ftie)
     568             : {
     569             :         u8 mic[16];
     570             : 
     571          41 :         if (peer->tpk_set) {
     572          41 :                 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
     573          41 :                                   peer->rsnie_p, timeoutie, (u8 *) ftie,
     574             :                                   mic);
     575          41 :                 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
     576           2 :                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
     577             :                                    "dropping packet");
     578           2 :                         wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
     579           2 :                                     ftie->mic, 16);
     580           2 :                         wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
     581             :                                     mic, 16);
     582           2 :                         return -1;
     583             :                 }
     584             :         } else {
     585           0 :                 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
     586             :                            "TPK not set - dropping packet");
     587           0 :                 return -1;
     588             :         }
     589          39 :         return 0;
     590             : }
     591             : 
     592             : 
     593          19 : static int wpa_supplicant_verify_tdls_mic_teardown(
     594             :         u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
     595             :         const u8 *lnkid, const struct wpa_tdls_ftie *ftie)
     596             : {
     597             :         u8 mic[16];
     598             : 
     599          19 :         if (peer->tpk_set) {
     600          19 :                 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
     601             :                                           dtoken, lnkid, (u8 *) ftie, mic);
     602          19 :                 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
     603           0 :                         wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
     604             :                                    "dropping packet");
     605           0 :                         return -1;
     606             :                 }
     607             :         } else {
     608           0 :                 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
     609             :                            "MIC, TPK not set - dropping packet");
     610           0 :                 return -1;
     611             :         }
     612          19 :         return 0;
     613             : }
     614             : 
     615             : 
     616           0 : static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
     617             : {
     618           0 :         struct wpa_sm *sm = eloop_ctx;
     619           0 :         struct wpa_tdls_peer *peer = timeout_ctx;
     620             : 
     621             :         /*
     622             :          * On TPK lifetime expiration, we have an option of either tearing down
     623             :          * the direct link or trying to re-initiate it. The selection of what
     624             :          * to do is not strictly speaking controlled by our role in the expired
     625             :          * link, but for now, use that to select whether to renew or tear down
     626             :          * the link.
     627             :          */
     628             : 
     629           0 :         if (peer->initiator) {
     630           0 :                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
     631           0 :                            " - try to renew", MAC2STR(peer->addr));
     632           0 :                 wpa_tdls_start(sm, peer->addr);
     633             :         } else {
     634           0 :                 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
     635           0 :                            " - tear down", MAC2STR(peer->addr));
     636           0 :                 wpa_tdls_do_teardown(sm, peer,
     637             :                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
     638             :         }
     639           0 : }
     640             : 
     641             : 
     642          61 : static void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm,
     643             :                                            struct wpa_tdls_peer *peer)
     644             : {
     645             :         struct wpa_tdls_peer *cur, *prev;
     646             : 
     647          61 :         cur = sm->tdls;
     648          61 :         prev = NULL;
     649         122 :         while (cur && cur != peer) {
     650           0 :                 prev = cur;
     651           0 :                 cur = cur->next;
     652             :         }
     653             : 
     654          61 :         if (cur != peer) {
     655           0 :                 wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR
     656             :                            " to remove it from the list",
     657           0 :                            MAC2STR(peer->addr));
     658          61 :                 return;
     659             :         }
     660             : 
     661          61 :         if (prev)
     662           0 :                 prev->next = peer->next;
     663             :         else
     664          61 :                 sm->tdls = peer->next;
     665             : }
     666             : 
     667             : 
     668          62 : static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
     669             : {
     670         372 :         wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
     671         372 :                    MAC2STR(peer->addr));
     672          62 :         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
     673          62 :         eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
     674          62 :         peer->reconfig_key = 0;
     675          62 :         peer->initiator = 0;
     676          62 :         peer->tpk_in_progress = 0;
     677          62 :         os_free(peer->sm_tmr.buf);
     678          62 :         peer->sm_tmr.buf = NULL;
     679          62 :         os_free(peer->ht_capabilities);
     680          62 :         peer->ht_capabilities = NULL;
     681          62 :         os_free(peer->vht_capabilities);
     682          62 :         peer->vht_capabilities = NULL;
     683          62 :         os_free(peer->ext_capab);
     684          62 :         peer->ext_capab = NULL;
     685          62 :         os_free(peer->supp_channels);
     686          62 :         peer->supp_channels = NULL;
     687          62 :         os_free(peer->supp_oper_classes);
     688          62 :         peer->supp_oper_classes = NULL;
     689          62 :         peer->rsnie_i_len = peer->rsnie_p_len = 0;
     690          62 :         peer->cipher = 0;
     691          62 :         peer->qos_info = 0;
     692          62 :         peer->wmm_capable = 0;
     693          62 :         peer->tpk_set = peer->tpk_success = 0;
     694          62 :         peer->chan_switch_enabled = 0;
     695          62 :         os_memset(&peer->tpk, 0, sizeof(peer->tpk));
     696          62 :         os_memset(peer->inonce, 0, WPA_NONCE_LEN);
     697          62 :         os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
     698          62 : }
     699             : 
     700             : 
     701          61 : static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
     702             : {
     703          61 :         wpa_tdls_peer_clear(sm, peer);
     704          61 :         wpa_tdls_peer_remove_from_list(sm, peer);
     705          61 :         os_free(peer);
     706          61 : }
     707             : 
     708             : 
     709          20 : static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
     710             :                             struct wpa_tdls_lnkid *lnkid)
     711             : {
     712          20 :         lnkid->ie_type = WLAN_EID_LINK_ID;
     713          20 :         lnkid->ie_len = 3 * ETH_ALEN;
     714          20 :         os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
     715          20 :         if (peer->initiator) {
     716          13 :                 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
     717          13 :                 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
     718             :         } else {
     719           7 :                 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
     720           7 :                 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
     721             :         }
     722          20 : }
     723             : 
     724             : 
     725          31 : static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
     726             :                                   u16 reason_code)
     727             : {
     728             :         struct wpa_tdls_peer *peer;
     729             :         struct wpa_tdls_ftie *ftie;
     730             :         struct wpa_tdls_lnkid lnkid;
     731             :         u8 dialog_token;
     732             :         u8 *rbuf, *pos;
     733             :         int ielen;
     734             : 
     735          31 :         if (sm->tdls_disabled || !sm->tdls_supported)
     736           0 :                 return -1;
     737             : 
     738             :         /* Find the node and free from the list */
     739          31 :         for (peer = sm->tdls; peer; peer = peer->next) {
     740          31 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
     741          31 :                         break;
     742             :         }
     743             : 
     744          31 :         if (peer == NULL) {
     745           0 :                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
     746           0 :                            "Teardown " MACSTR, MAC2STR(addr));
     747           0 :                 return 0;
     748             :         }
     749             : 
     750             :         /* Cancel active channel switch before teardown */
     751          31 :         if (peer->chan_switch_enabled) {
     752           0 :                 wpa_printf(MSG_DEBUG, "TDLS: First returning link with " MACSTR
     753           0 :                            " to base channel", MAC2STR(addr));
     754           0 :                 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
     755             :         }
     756             : 
     757          31 :         dialog_token = peer->dtoken;
     758             : 
     759         186 :         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
     760         186 :                    MAC2STR(addr));
     761             : 
     762          31 :         ielen = 0;
     763          31 :         if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
     764             :                 /* To add FTIE for Teardown request and compute MIC */
     765          20 :                 ielen += sizeof(*ftie);
     766             : #ifdef CONFIG_TDLS_TESTING
     767          20 :                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
     768           2 :                         ielen += 170;
     769             : #endif /* CONFIG_TDLS_TESTING */
     770             :         }
     771             : 
     772          31 :         rbuf = os_zalloc(ielen + 1);
     773          31 :         if (rbuf == NULL)
     774           0 :                 return -1;
     775          31 :         pos = rbuf;
     776             : 
     777          31 :         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
     778             :                 goto skip_ies;
     779             : 
     780          20 :         ftie = (struct wpa_tdls_ftie *) pos;
     781          20 :         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
     782             :         /* Using the recent nonce which should be for CONFIRM frame */
     783          20 :         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
     784          20 :         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
     785          20 :         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
     786          20 :         pos = (u8 *) (ftie + 1);
     787             : #ifdef CONFIG_TDLS_TESTING
     788          20 :         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
     789           2 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
     790             :                            "FTIE");
     791           2 :                 ftie->ie_len += 170;
     792           2 :                 *pos++ = 255; /* FTIE subelem */
     793           2 :                 *pos++ = 168; /* FTIE subelem length */
     794           2 :                 pos += 168;
     795             :         }
     796             : #endif /* CONFIG_TDLS_TESTING */
     797          20 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
     798          20 :                     (u8 *) ftie, pos - (u8 *) ftie);
     799             : 
     800             :         /* compute MIC before sending */
     801          20 :         wpa_tdls_linkid(sm, peer, &lnkid);
     802          20 :         wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
     803             :                                   dialog_token, (u8 *) &lnkid, (u8 *) ftie,
     804          20 :                                   ftie->mic);
     805             : 
     806             : skip_ies:
     807             :         /* TODO: register for a Timeout handler, if Teardown is not received at
     808             :          * the other end, then try again another time */
     809             : 
     810             :         /* request driver to send Teardown using this FTIE */
     811          31 :         wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
     812          31 :                           reason_code, 0, peer->initiator, rbuf, pos - rbuf);
     813          31 :         os_free(rbuf);
     814             : 
     815          31 :         return 0;
     816             : }
     817             : 
     818             : 
     819          13 : int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
     820             : {
     821             :         struct wpa_tdls_peer *peer;
     822             : 
     823          13 :         if (sm->tdls_disabled || !sm->tdls_supported)
     824           0 :                 return -1;
     825             : 
     826          13 :         for (peer = sm->tdls; peer; peer = peer->next) {
     827          12 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
     828          12 :                         break;
     829             :         }
     830             : 
     831          13 :         if (peer == NULL) {
     832           6 :                 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
     833           6 :                    " for link Teardown", MAC2STR(addr));
     834           1 :                 return -1;
     835             :         }
     836             : 
     837          12 :         if (!peer->tpk_success) {
     838           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
     839           0 :                    " not connected - cannot Teardown link", MAC2STR(addr));
     840           0 :                 return -1;
     841             :         }
     842             : 
     843          12 :         return wpa_tdls_do_teardown(sm, peer, reason_code);
     844             : }
     845             : 
     846             : 
     847          60 : static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
     848             :                                        struct wpa_tdls_peer *peer)
     849             : {
     850          60 :         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
     851          60 :         wpa_tdls_peer_free(sm, peer);
     852          60 : }
     853             : 
     854             : 
     855           0 : void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
     856             : {
     857             :         struct wpa_tdls_peer *peer;
     858             : 
     859           0 :         for (peer = sm->tdls; peer; peer = peer->next) {
     860           0 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
     861           0 :                         break;
     862             :         }
     863             : 
     864           0 :         if (!peer || !peer->tpk_success) {
     865           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
     866             :                            " not connected - cannot teardown unreachable link",
     867           0 :                            MAC2STR(addr));
     868           0 :                 return;
     869             :         }
     870             : 
     871           0 :         if (wpa_tdls_is_external_setup(sm)) {
     872             :                 /*
     873             :                  * Get us on the base channel, disable the link, send a
     874             :                  * teardown packet through the AP, and then reset link data.
     875             :                  */
     876           0 :                 if (peer->chan_switch_enabled)
     877           0 :                         wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
     878           0 :                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
     879           0 :                 wpa_tdls_send_teardown(sm, addr,
     880             :                                        WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
     881           0 :                 wpa_tdls_peer_free(sm, peer);
     882             :         } else {
     883           0 :                 wpa_tdls_disable_peer_link(sm, peer);
     884             :         }
     885             : }
     886             : 
     887             : 
     888           9 : const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr)
     889             : {
     890             :         struct wpa_tdls_peer *peer;
     891             : 
     892           9 :         if (sm->tdls_disabled || !sm->tdls_supported)
     893           0 :                 return "disabled";
     894             : 
     895           9 :         for (peer = sm->tdls; peer; peer = peer->next) {
     896           3 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
     897           3 :                         break;
     898             :         }
     899             : 
     900           9 :         if (peer == NULL)
     901           6 :                 return "peer does not exist";
     902             : 
     903           3 :         if (!peer->tpk_success)
     904           0 :                 return "peer not connected";
     905             : 
     906           3 :         return "connected";
     907             : }
     908             : 
     909             : 
     910          29 : static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
     911             :                                   const u8 *buf, size_t len)
     912             : {
     913          29 :         struct wpa_tdls_peer *peer = NULL;
     914             :         struct wpa_tdls_ftie *ftie;
     915             :         struct wpa_tdls_lnkid *lnkid;
     916             :         struct wpa_eapol_ie_parse kde;
     917             :         u16 reason_code;
     918             :         const u8 *pos;
     919             :         int ielen;
     920             : 
     921             :         /* Find the node and free from the list */
     922          29 :         for (peer = sm->tdls; peer; peer = peer->next) {
     923          26 :                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
     924          26 :                         break;
     925             :         }
     926             : 
     927          29 :         if (peer == NULL) {
     928          18 :                 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
     929          18 :                            "Teardown " MACSTR, MAC2STR(src_addr));
     930           3 :                 return 0;
     931             :         }
     932             : 
     933          26 :         pos = buf;
     934          26 :         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
     935             : 
     936          26 :         reason_code = WPA_GET_LE16(pos);
     937          26 :         pos += 2;
     938             : 
     939         182 :         wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
     940         156 :                    " (reason code %u)", MAC2STR(src_addr), reason_code);
     941             : 
     942          26 :         ielen = len - (pos - buf); /* start of IE in buf */
     943             : 
     944             :         /*
     945             :          * Don't reject the message if failing to parse IEs. The IEs we need are
     946             :          * explicitly checked below. Some APs may add arbitrary padding to the
     947             :          * end of short TDLS frames and that would look like invalid IEs.
     948             :          */
     949          26 :         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0)
     950           0 :                 wpa_printf(MSG_DEBUG,
     951             :                            "TDLS: Failed to parse IEs in Teardown - ignore as an interop workaround");
     952             : 
     953          26 :         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
     954           0 :                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
     955             :                            "Teardown");
     956           0 :                 return -1;
     957             :         }
     958          26 :         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
     959             : 
     960          26 :         if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
     961             :                 goto skip_ftie;
     962             : 
     963          20 :         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
     964           1 :                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
     965           1 :                 return -1;
     966             :         }
     967             : 
     968          19 :         ftie = (struct wpa_tdls_ftie *) kde.ftie;
     969             : 
     970             :         /* Process MIC check to see if TDLS Teardown is right */
     971          19 :         if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
     972          19 :                                                     peer->dtoken, peer,
     973             :                                                     (u8 *) lnkid, ftie) < 0) {
     974           0 :                 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
     975           0 :                            "Teardown Request from " MACSTR, MAC2STR(src_addr));
     976           0 :                 return -1;
     977             :         }
     978             : 
     979             : skip_ftie:
     980             :         /*
     981             :          * Request the driver to disable the direct link and clear associated
     982             :          * keys.
     983             :          */
     984          25 :         wpa_tdls_disable_peer_link(sm, peer);
     985          25 :         return 0;
     986             : }
     987             : 
     988             : 
     989             : /**
     990             :  * wpa_tdls_send_error - To send suitable TDLS status response with
     991             :  *      appropriate status code mentioning reason for error/failure.
     992             :  * @dst         - MAC addr of Peer station
     993             :  * @tdls_action - TDLS frame type for which error code is sent
     994             :  * @initiator   - was this end the initiator of the connection
     995             :  * @status      - status code mentioning reason
     996             :  */
     997             : 
     998           3 : static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
     999             :                                u8 tdls_action, u8 dialog_token, int initiator,
    1000             :                                u16 status)
    1001             : {
    1002          21 :         wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
    1003             :                    " (action=%u status=%u)",
    1004          18 :                    MAC2STR(dst), tdls_action, status);
    1005           3 :         return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
    1006             :                                  0, initiator, NULL, 0);
    1007             : }
    1008             : 
    1009             : 
    1010             : static struct wpa_tdls_peer *
    1011          67 : wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing)
    1012             : {
    1013             :         struct wpa_tdls_peer *peer;
    1014             : 
    1015          67 :         if (existing)
    1016          32 :                 *existing = 0;
    1017          67 :         for (peer = sm->tdls; peer; peer = peer->next) {
    1018           5 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
    1019           5 :                         if (existing)
    1020           3 :                                 *existing = 1;
    1021           5 :                         return peer; /* re-use existing entry */
    1022             :                 }
    1023             :         }
    1024             : 
    1025         372 :         wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
    1026         372 :                    MAC2STR(addr));
    1027             : 
    1028          62 :         peer = os_zalloc(sizeof(*peer));
    1029          62 :         if (peer == NULL)
    1030           1 :                 return NULL;
    1031             : 
    1032          61 :         os_memcpy(peer->addr, addr, ETH_ALEN);
    1033          61 :         peer->next = sm->tdls;
    1034          61 :         sm->tdls = peer;
    1035             : 
    1036          61 :         return peer;
    1037             : }
    1038             : 
    1039             : 
    1040          32 : static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
    1041             :                                 struct wpa_tdls_peer *peer)
    1042             : {
    1043             :         size_t buf_len;
    1044             :         struct wpa_tdls_timeoutie timeoutie;
    1045             :         u16 rsn_capab;
    1046             :         struct wpa_tdls_ftie *ftie;
    1047             :         u8 *rbuf, *pos, *count_pos;
    1048             :         u16 count;
    1049             :         struct rsn_ie_hdr *hdr;
    1050             :         int status;
    1051             : 
    1052          32 :         if (!wpa_tdls_get_privacy(sm)) {
    1053           6 :                 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
    1054           6 :                 peer->rsnie_i_len = 0;
    1055           6 :                 goto skip_rsnie;
    1056             :         }
    1057             : 
    1058             :         /*
    1059             :          * TPK Handshake Message 1:
    1060             :          * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
    1061             :          * Timeout Interval IE))
    1062             :          */
    1063             : 
    1064             :         /* Filling RSN IE */
    1065          26 :         hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
    1066          26 :         hdr->elem_id = WLAN_EID_RSN;
    1067          26 :         WPA_PUT_LE16(hdr->version, RSN_VERSION);
    1068             : 
    1069          26 :         pos = (u8 *) (hdr + 1);
    1070          26 :         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
    1071          26 :         pos += RSN_SELECTOR_LEN;
    1072          26 :         count_pos = pos;
    1073          26 :         pos += 2;
    1074             : 
    1075          26 :         count = 0;
    1076             : 
    1077             :         /*
    1078             :          * AES-CCMP is the default Encryption preferred for TDLS, so
    1079             :          * RSN IE is filled only with CCMP CIPHER
    1080             :          * Note: TKIP is not used to encrypt TDLS link.
    1081             :          *
    1082             :          * Regardless of the cipher used on the AP connection, select CCMP
    1083             :          * here.
    1084             :          */
    1085          26 :         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
    1086          26 :         pos += RSN_SELECTOR_LEN;
    1087          26 :         count++;
    1088             : 
    1089          26 :         WPA_PUT_LE16(count_pos, count);
    1090             : 
    1091          26 :         WPA_PUT_LE16(pos, 1);
    1092          26 :         pos += 2;
    1093          26 :         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
    1094          26 :         pos += RSN_SELECTOR_LEN;
    1095             : 
    1096          26 :         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
    1097          26 :         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
    1098             : #ifdef CONFIG_TDLS_TESTING
    1099          26 :         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
    1100           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
    1101             :                            "testing");
    1102           1 :                 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
    1103             :         }
    1104             : #endif /* CONFIG_TDLS_TESTING */
    1105          26 :         WPA_PUT_LE16(pos, rsn_capab);
    1106          26 :         pos += 2;
    1107             : #ifdef CONFIG_TDLS_TESTING
    1108          26 :         if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
    1109             :                 /* Number of PMKIDs */
    1110           1 :                 *pos++ = 0x00;
    1111           1 :                 *pos++ = 0x00;
    1112             :         }
    1113             : #endif /* CONFIG_TDLS_TESTING */
    1114             : 
    1115          26 :         hdr->len = (pos - peer->rsnie_i) - 2;
    1116          26 :         peer->rsnie_i_len = pos - peer->rsnie_i;
    1117          52 :         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
    1118          26 :                     peer->rsnie_i, peer->rsnie_i_len);
    1119             : 
    1120             : skip_rsnie:
    1121          32 :         buf_len = 0;
    1122          32 :         if (wpa_tdls_get_privacy(sm))
    1123          26 :                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
    1124             :                         sizeof(struct wpa_tdls_timeoutie);
    1125             : #ifdef CONFIG_TDLS_TESTING
    1126          58 :         if (wpa_tdls_get_privacy(sm) &&
    1127          26 :             (tdls_testing & TDLS_TESTING_LONG_FRAME))
    1128           2 :                 buf_len += 170;
    1129          32 :         if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
    1130           0 :                 buf_len += sizeof(struct wpa_tdls_lnkid);
    1131             : #endif /* CONFIG_TDLS_TESTING */
    1132          32 :         rbuf = os_zalloc(buf_len + 1);
    1133          32 :         if (rbuf == NULL) {
    1134           0 :                 wpa_tdls_peer_free(sm, peer);
    1135           0 :                 return -1;
    1136             :         }
    1137          32 :         pos = rbuf;
    1138             : 
    1139          32 :         if (!wpa_tdls_get_privacy(sm))
    1140           6 :                 goto skip_ies;
    1141             : 
    1142             :         /* Initiator RSN IE */
    1143          26 :         pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
    1144             : 
    1145          26 :         ftie = (struct wpa_tdls_ftie *) pos;
    1146          26 :         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
    1147          26 :         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
    1148             : 
    1149          26 :         if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
    1150           0 :                 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
    1151             :                         "TDLS: Failed to get random data for initiator Nonce");
    1152           0 :                 os_free(rbuf);
    1153           0 :                 wpa_tdls_peer_free(sm, peer);
    1154           0 :                 return -1;
    1155             :         }
    1156          26 :         wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
    1157          26 :                     peer->inonce, WPA_NONCE_LEN);
    1158          26 :         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
    1159             : 
    1160          26 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
    1161             :                     (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
    1162             : 
    1163          26 :         pos = (u8 *) (ftie + 1);
    1164             : 
    1165             : #ifdef CONFIG_TDLS_TESTING
    1166          26 :         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
    1167           2 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
    1168             :                            "FTIE");
    1169           2 :                 ftie->ie_len += 170;
    1170           2 :                 *pos++ = 255; /* FTIE subelem */
    1171           2 :                 *pos++ = 168; /* FTIE subelem length */
    1172           2 :                 pos += 168;
    1173             :         }
    1174             : #endif /* CONFIG_TDLS_TESTING */
    1175             : 
    1176             :         /* Lifetime */
    1177          26 :         peer->lifetime = TPK_LIFETIME;
    1178             : #ifdef CONFIG_TDLS_TESTING
    1179          26 :         if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
    1180           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
    1181             :                            "lifetime");
    1182           0 :                 peer->lifetime = 301;
    1183             :         }
    1184          26 :         if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
    1185           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
    1186             :                            "lifetime");
    1187           1 :                 peer->lifetime = 0xffffffff;
    1188             :         }
    1189             : #endif /* CONFIG_TDLS_TESTING */
    1190          26 :         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
    1191             :                                      sizeof(timeoutie), peer->lifetime);
    1192          26 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
    1193             : 
    1194             : skip_ies:
    1195             : 
    1196             : #ifdef CONFIG_TDLS_TESTING
    1197          32 :         if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
    1198           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
    1199             :                            "Link Identifier");
    1200           0 :                 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
    1201           0 :                 wpa_tdls_linkid(sm, peer, l);
    1202           0 :                 l->bssid[5] ^= 0x01;
    1203           0 :                 pos += sizeof(*l);
    1204             :         }
    1205             : #endif /* CONFIG_TDLS_TESTING */
    1206             : 
    1207         192 :         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
    1208             :                    "Handshake Message 1 (peer " MACSTR ")",
    1209         192 :                    MAC2STR(peer->addr));
    1210             : 
    1211          32 :         status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
    1212          32 :                                    1, 0, 0, peer->initiator, rbuf, pos - rbuf);
    1213          32 :         os_free(rbuf);
    1214             : 
    1215          32 :         return status;
    1216             : }
    1217             : 
    1218             : 
    1219          30 : static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
    1220             :                                 const unsigned char *src_addr, u8 dtoken,
    1221             :                                 struct wpa_tdls_lnkid *lnkid,
    1222             :                                 const struct wpa_tdls_peer *peer)
    1223             : {
    1224             :         u8 *rbuf, *pos;
    1225             :         size_t buf_len;
    1226             :         u32 lifetime;
    1227             :         struct wpa_tdls_timeoutie timeoutie;
    1228             :         struct wpa_tdls_ftie *ftie;
    1229             :         int status;
    1230             : 
    1231          30 :         buf_len = 0;
    1232          30 :         if (wpa_tdls_get_privacy(sm)) {
    1233             :                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
    1234             :                  * Lifetime */
    1235          24 :                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
    1236             :                         sizeof(struct wpa_tdls_timeoutie);
    1237             : #ifdef CONFIG_TDLS_TESTING
    1238          24 :                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
    1239           2 :                         buf_len += 170;
    1240             : #endif /* CONFIG_TDLS_TESTING */
    1241             :         }
    1242             : 
    1243          30 :         rbuf = os_zalloc(buf_len + 1);
    1244          30 :         if (rbuf == NULL)
    1245           0 :                 return -1;
    1246          30 :         pos = rbuf;
    1247             : 
    1248          30 :         if (!wpa_tdls_get_privacy(sm))
    1249           6 :                 goto skip_ies;
    1250             : 
    1251             :         /* Peer RSN IE */
    1252          24 :         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
    1253             : 
    1254          24 :         ftie = (struct wpa_tdls_ftie *) pos;
    1255          24 :         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
    1256             :         /* TODO: ftie->mic_control to set 2-RESPONSE */
    1257          24 :         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
    1258          24 :         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
    1259          24 :         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
    1260          24 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
    1261             :                     (u8 *) ftie, sizeof(*ftie));
    1262             : 
    1263          24 :         pos = (u8 *) (ftie + 1);
    1264             : 
    1265             : #ifdef CONFIG_TDLS_TESTING
    1266          24 :         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
    1267           2 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
    1268             :                            "FTIE");
    1269           2 :                 ftie->ie_len += 170;
    1270           2 :                 *pos++ = 255; /* FTIE subelem */
    1271           2 :                 *pos++ = 168; /* FTIE subelem length */
    1272           2 :                 pos += 168;
    1273             :         }
    1274             : #endif /* CONFIG_TDLS_TESTING */
    1275             : 
    1276             :         /* Lifetime */
    1277          24 :         lifetime = peer->lifetime;
    1278             : #ifdef CONFIG_TDLS_TESTING
    1279          24 :         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
    1280           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
    1281             :                            "lifetime in response");
    1282           1 :                 lifetime++;
    1283             :         }
    1284             : #endif /* CONFIG_TDLS_TESTING */
    1285          24 :         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
    1286             :                                      sizeof(timeoutie), lifetime);
    1287          24 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
    1288             :                    lifetime);
    1289             : 
    1290             :         /* compute MIC before sending */
    1291          24 :         wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p,
    1292          24 :                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
    1293             : #ifdef CONFIG_TDLS_TESTING
    1294          24 :         if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
    1295           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
    1296           1 :                 ftie->mic[0] ^= 0x01;
    1297             :         }
    1298             : #endif /* CONFIG_TDLS_TESTING */
    1299             : 
    1300             : skip_ies:
    1301          30 :         status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
    1302             :                                    dtoken, 0, 0, peer->initiator, rbuf,
    1303          30 :                                    pos - rbuf);
    1304          30 :         os_free(rbuf);
    1305             : 
    1306          30 :         return status;
    1307             : }
    1308             : 
    1309             : 
    1310          26 : static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
    1311             :                                 const unsigned char *src_addr, u8 dtoken,
    1312             :                                 struct wpa_tdls_lnkid *lnkid,
    1313             :                                 const struct wpa_tdls_peer *peer)
    1314             : {
    1315             :         u8 *rbuf, *pos;
    1316             :         size_t buf_len;
    1317             :         struct wpa_tdls_ftie *ftie;
    1318             :         struct wpa_tdls_timeoutie timeoutie;
    1319             :         u32 lifetime;
    1320             :         int status;
    1321          26 :         u32 peer_capab = 0;
    1322             : 
    1323          26 :         buf_len = 0;
    1324          26 :         if (wpa_tdls_get_privacy(sm)) {
    1325             :                 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
    1326             :                  * Lifetime */
    1327          20 :                 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
    1328             :                         sizeof(struct wpa_tdls_timeoutie);
    1329             : #ifdef CONFIG_TDLS_TESTING
    1330          20 :                 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
    1331           2 :                         buf_len += 170;
    1332             : #endif /* CONFIG_TDLS_TESTING */
    1333             :         }
    1334             : 
    1335          26 :         rbuf = os_zalloc(buf_len + 1);
    1336          26 :         if (rbuf == NULL)
    1337           0 :                 return -1;
    1338          26 :         pos = rbuf;
    1339             : 
    1340          26 :         if (!wpa_tdls_get_privacy(sm))
    1341           6 :                 goto skip_ies;
    1342             : 
    1343             :         /* Peer RSN IE */
    1344          20 :         pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
    1345             : 
    1346          20 :         ftie = (struct wpa_tdls_ftie *) pos;
    1347          20 :         ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
    1348             :         /*TODO: ftie->mic_control to set 3-CONFIRM */
    1349          20 :         os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
    1350          20 :         os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
    1351          20 :         ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
    1352             : 
    1353          20 :         pos = (u8 *) (ftie + 1);
    1354             : 
    1355             : #ifdef CONFIG_TDLS_TESTING
    1356          20 :         if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
    1357           2 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
    1358             :                            "FTIE");
    1359           2 :                 ftie->ie_len += 170;
    1360           2 :                 *pos++ = 255; /* FTIE subelem */
    1361           2 :                 *pos++ = 168; /* FTIE subelem length */
    1362           2 :                 pos += 168;
    1363             :         }
    1364             : #endif /* CONFIG_TDLS_TESTING */
    1365             : 
    1366             :         /* Lifetime */
    1367          20 :         lifetime = peer->lifetime;
    1368             : #ifdef CONFIG_TDLS_TESTING
    1369          20 :         if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
    1370           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
    1371             :                            "lifetime in confirm");
    1372           0 :                 lifetime++;
    1373             :         }
    1374             : #endif /* CONFIG_TDLS_TESTING */
    1375          20 :         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
    1376             :                                      sizeof(timeoutie), lifetime);
    1377          20 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
    1378             :                    lifetime);
    1379             : 
    1380             :         /* compute MIC before sending */
    1381          20 :         wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
    1382          20 :                           (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
    1383             : #ifdef CONFIG_TDLS_TESTING
    1384          20 :         if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
    1385           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
    1386           1 :                 ftie->mic[0] ^= 0x01;
    1387             :         }
    1388             : #endif /* CONFIG_TDLS_TESTING */
    1389             : 
    1390             : skip_ies:
    1391             : 
    1392          26 :         if (peer->vht_capabilities)
    1393           2 :                 peer_capab |= TDLS_PEER_VHT;
    1394          26 :         if (peer->ht_capabilities)
    1395          25 :                 peer_capab |= TDLS_PEER_HT;
    1396          26 :         if (peer->wmm_capable)
    1397          26 :                 peer_capab |= TDLS_PEER_WMM;
    1398             : 
    1399          26 :         status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
    1400             :                                    dtoken, 0, peer_capab, peer->initiator,
    1401          26 :                                    rbuf, pos - rbuf);
    1402          26 :         os_free(rbuf);
    1403             : 
    1404          26 :         return status;
    1405             : }
    1406             : 
    1407             : 
    1408           2 : static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
    1409             :                                             struct wpa_tdls_peer *peer,
    1410             :                                             u8 dialog_token)
    1411             : {
    1412           2 :         size_t buf_len = 0;
    1413             :         struct wpa_tdls_timeoutie timeoutie;
    1414             :         u16 rsn_capab;
    1415             :         u8 *rbuf, *pos, *count_pos;
    1416             :         u16 count;
    1417             :         struct rsn_ie_hdr *hdr;
    1418             :         int status;
    1419             : 
    1420          12 :         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
    1421          12 :                    "(peer " MACSTR ")", MAC2STR(peer->addr));
    1422           2 :         if (!wpa_tdls_get_privacy(sm))
    1423           1 :                 goto skip_rsn_ies;
    1424             : 
    1425             :         /* Filling RSN IE */
    1426           1 :         hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
    1427           1 :         hdr->elem_id = WLAN_EID_RSN;
    1428           1 :         WPA_PUT_LE16(hdr->version, RSN_VERSION);
    1429           1 :         pos = (u8 *) (hdr + 1);
    1430           1 :         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
    1431           1 :         pos += RSN_SELECTOR_LEN;
    1432           1 :         count_pos = pos;
    1433           1 :         pos += 2;
    1434           1 :         count = 0;
    1435             : 
    1436             :         /*
    1437             :         * AES-CCMP is the default encryption preferred for TDLS, so
    1438             :         * RSN IE is filled only with CCMP cipher suite.
    1439             :         * Note: TKIP is not used to encrypt TDLS link.
    1440             :         *
    1441             :         * Regardless of the cipher used on the AP connection, select CCMP
    1442             :         * here.
    1443             :         */
    1444           1 :         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
    1445           1 :         pos += RSN_SELECTOR_LEN;
    1446           1 :         count++;
    1447           1 :         WPA_PUT_LE16(count_pos, count);
    1448           1 :         WPA_PUT_LE16(pos, 1);
    1449           1 :         pos += 2;
    1450           1 :         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
    1451           1 :         pos += RSN_SELECTOR_LEN;
    1452             : 
    1453           1 :         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
    1454           1 :         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
    1455           1 :         WPA_PUT_LE16(pos, rsn_capab);
    1456           1 :         pos += 2;
    1457           1 :         hdr->len = (pos - (u8 *) hdr) - 2;
    1458           1 :         peer->rsnie_i_len = pos - peer->rsnie_i;
    1459             : 
    1460           1 :         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
    1461           1 :                     (u8 *) hdr, hdr->len + 2);
    1462             : skip_rsn_ies:
    1463           2 :         buf_len = 0;
    1464           2 :         if (wpa_tdls_get_privacy(sm)) {
    1465             :                 /* Peer RSN IE, Lifetime */
    1466           1 :                 buf_len += peer->rsnie_i_len +
    1467             :                         sizeof(struct wpa_tdls_timeoutie);
    1468             :         }
    1469           2 :         rbuf = os_zalloc(buf_len + 1);
    1470           2 :         if (rbuf == NULL) {
    1471           0 :                 wpa_tdls_peer_free(sm, peer);
    1472           0 :                 return -1;
    1473             :         }
    1474           2 :         pos = rbuf;
    1475             : 
    1476           2 :         if (!wpa_tdls_get_privacy(sm))
    1477           1 :                 goto skip_ies;
    1478             :         /* Initiator RSN IE */
    1479           1 :         pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
    1480             :         /* Lifetime */
    1481           1 :         peer->lifetime = TPK_LIFETIME;
    1482           1 :         pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
    1483             :                                      sizeof(timeoutie), peer->lifetime);
    1484           1 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
    1485             : skip_ies:
    1486           2 :         status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
    1487           2 :                                    dialog_token, 0, 0, 0, rbuf, pos - rbuf);
    1488           2 :         os_free(rbuf);
    1489             : 
    1490           2 :         return status;
    1491             : }
    1492             : 
    1493             : 
    1494             : static int
    1495           2 : wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
    1496             :                                    const u8 *buf, size_t len)
    1497             : {
    1498             :         struct wpa_eapol_ie_parse kde;
    1499             :         const struct wpa_tdls_lnkid *lnkid;
    1500             :         struct wpa_tdls_peer *peer;
    1501           2 :         size_t min_req_len = sizeof(struct wpa_tdls_frame) +
    1502             :                 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
    1503             :         u8 dialog_token;
    1504             : 
    1505          12 :         wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
    1506          12 :                    MAC2STR(addr));
    1507             : 
    1508           2 :         if (len < min_req_len) {
    1509           0 :                 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
    1510             :                            "%d", (int) len);
    1511           0 :                 return -1;
    1512             :         }
    1513             : 
    1514           2 :         dialog_token = buf[sizeof(struct wpa_tdls_frame)];
    1515             : 
    1516             :         /*
    1517             :          * Some APs will tack on a weird IE to the end of a TDLS
    1518             :          * discovery request packet. This needn't fail the response,
    1519             :          * since the required IE are verified separately.
    1520             :          */
    1521           2 :         if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
    1522             :                                      len - (sizeof(struct wpa_tdls_frame) + 1),
    1523             :                                      &kde) < 0) {
    1524           0 :                 wpa_printf(MSG_DEBUG,
    1525             :                            "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround");
    1526             :         }
    1527             : 
    1528           2 :         if (!kde.lnkid) {
    1529           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
    1530             :                            "Request");
    1531           0 :                 return -1;
    1532             :         }
    1533             : 
    1534           2 :         lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
    1535             : 
    1536           2 :         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
    1537           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
    1538           0 :                            " BSS " MACSTR, MAC2STR(lnkid->bssid));
    1539           0 :                 return -1;
    1540             :         }
    1541             : 
    1542           2 :         peer = wpa_tdls_add_peer(sm, addr, NULL);
    1543           2 :         if (peer == NULL)
    1544           0 :                 return -1;
    1545             : 
    1546           2 :         return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
    1547             : }
    1548             : 
    1549             : 
    1550           3 : int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
    1551             : {
    1552           3 :         if (sm->tdls_disabled || !sm->tdls_supported)
    1553           0 :                 return -1;
    1554             : 
    1555          18 :         wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
    1556          18 :                    MACSTR, MAC2STR(addr));
    1557           3 :         return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
    1558             :                                  1, 0, 0, 1, NULL, 0);
    1559             : }
    1560             : 
    1561             : 
    1562          58 : static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
    1563             :                            struct wpa_tdls_peer *peer)
    1564             : {
    1565          58 :         if (!kde->supp_rates) {
    1566           0 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported rates received");
    1567           0 :                 return -1;
    1568             :         }
    1569         344 :         peer->supp_rates_len = merge_byte_arrays(
    1570          58 :                 peer->supp_rates, sizeof(peer->supp_rates),
    1571         116 :                 kde->supp_rates + 2, kde->supp_rates_len - 2,
    1572         112 :                 kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL,
    1573          58 :                 kde->ext_supp_rates_len - 2);
    1574          58 :         return 0;
    1575             : }
    1576             : 
    1577             : 
    1578          58 : static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
    1579             :                               struct wpa_tdls_peer *peer)
    1580             : {
    1581          58 :         if (!kde->ht_capabilities) {
    1582           1 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
    1583             :                            "received");
    1584           1 :                 return 0;
    1585             :         }
    1586             : 
    1587          57 :         if (!peer->ht_capabilities) {
    1588          56 :                 peer->ht_capabilities =
    1589          56 :                         os_zalloc(sizeof(struct ieee80211_ht_capabilities));
    1590          56 :                 if (peer->ht_capabilities == NULL)
    1591           0 :                         return -1;
    1592             :         }
    1593             : 
    1594          57 :         os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
    1595             :                   sizeof(struct ieee80211_ht_capabilities));
    1596          57 :         wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
    1597          57 :                     (u8 *) peer->ht_capabilities,
    1598             :                     sizeof(struct ieee80211_ht_capabilities));
    1599             : 
    1600          57 :         return 0;
    1601             : }
    1602             : 
    1603             : 
    1604          58 : static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde,
    1605             :                               struct wpa_tdls_peer *peer)
    1606             : {
    1607          58 :         if (!kde->vht_capabilities) {
    1608          54 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities "
    1609             :                            "received");
    1610          54 :                 return 0;
    1611             :         }
    1612             : 
    1613           4 :         if (!peer->vht_capabilities) {
    1614           4 :                 peer->vht_capabilities =
    1615           4 :                         os_zalloc(sizeof(struct ieee80211_vht_capabilities));
    1616           4 :                 if (peer->vht_capabilities == NULL)
    1617           0 :                         return -1;
    1618             :         }
    1619             : 
    1620           4 :         os_memcpy(peer->vht_capabilities, kde->vht_capabilities,
    1621             :                   sizeof(struct ieee80211_vht_capabilities));
    1622           4 :         wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities",
    1623           4 :                     (u8 *) peer->vht_capabilities,
    1624             :                     sizeof(struct ieee80211_vht_capabilities));
    1625             : 
    1626           4 :         return 0;
    1627             : }
    1628             : 
    1629             : 
    1630          58 : static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
    1631             :                                struct wpa_tdls_peer *peer)
    1632             : {
    1633          58 :         if (!kde->ext_capab) {
    1634           0 :                 wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities "
    1635             :                            "received");
    1636           0 :                 return 0;
    1637             :         }
    1638             : 
    1639          58 :         if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) {
    1640             :                 /* Need to allocate buffer to fit the new information */
    1641          57 :                 os_free(peer->ext_capab);
    1642          57 :                 peer->ext_capab = os_zalloc(kde->ext_capab_len - 2);
    1643          57 :                 if (peer->ext_capab == NULL)
    1644           0 :                         return -1;
    1645             :         }
    1646             : 
    1647          58 :         peer->ext_capab_len = kde->ext_capab_len - 2;
    1648          58 :         os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len);
    1649             : 
    1650          58 :         return 0;
    1651             : }
    1652             : 
    1653             : 
    1654          58 : static int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde,
    1655             :                                struct wpa_tdls_peer *peer)
    1656             : {
    1657             :         struct wmm_information_element *wmm;
    1658             : 
    1659          58 :         if (!kde->wmm) {
    1660           0 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received");
    1661           0 :                 return 0;
    1662             :         }
    1663             : 
    1664          58 :         if (kde->wmm_len < sizeof(struct wmm_information_element)) {
    1665           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received");
    1666           0 :                 return -1;
    1667             :         }
    1668             : 
    1669          58 :         wmm = (struct wmm_information_element *) kde->wmm;
    1670          58 :         peer->qos_info = wmm->qos_info;
    1671             : 
    1672          58 :         peer->wmm_capable = 1;
    1673             : 
    1674          58 :         wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info);
    1675          58 :         return 0;
    1676             : }
    1677             : 
    1678             : 
    1679          58 : static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
    1680             :                                    struct wpa_tdls_peer *peer)
    1681             : {
    1682          58 :         if (!kde->supp_channels) {
    1683           0 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
    1684           0 :                 return 0;
    1685             :         }
    1686             : 
    1687          59 :         if (!peer->supp_channels ||
    1688           1 :             peer->supp_channels_len < kde->supp_channels_len) {
    1689          57 :                 os_free(peer->supp_channels);
    1690          57 :                 peer->supp_channels = os_zalloc(kde->supp_channels_len);
    1691          57 :                 if (peer->supp_channels == NULL)
    1692           0 :                         return -1;
    1693             :         }
    1694             : 
    1695          58 :         peer->supp_channels_len = kde->supp_channels_len;
    1696             : 
    1697          58 :         os_memcpy(peer->supp_channels, kde->supp_channels,
    1698             :                   peer->supp_channels_len);
    1699         116 :         wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
    1700          58 :                     (u8 *) peer->supp_channels, peer->supp_channels_len);
    1701          58 :         return 0;
    1702             : }
    1703             : 
    1704             : 
    1705          58 : static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
    1706             :                                        struct wpa_tdls_peer *peer)
    1707             : {
    1708          58 :         if (!kde->supp_oper_classes) {
    1709           0 :                 wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
    1710           0 :                 return 0;
    1711             :         }
    1712             : 
    1713          59 :         if (!peer->supp_oper_classes ||
    1714           1 :             peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
    1715          57 :                 os_free(peer->supp_oper_classes);
    1716          57 :                 peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
    1717          57 :                 if (peer->supp_oper_classes == NULL)
    1718           0 :                         return -1;
    1719             :         }
    1720             : 
    1721          58 :         peer->supp_oper_classes_len = kde->supp_oper_classes_len;
    1722          58 :         os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
    1723             :                   peer->supp_oper_classes_len);
    1724         116 :         wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
    1725          58 :                     (u8 *) peer->supp_oper_classes,
    1726             :                     peer->supp_oper_classes_len);
    1727          58 :         return 0;
    1728             : }
    1729             : 
    1730             : 
    1731          79 : static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
    1732             :                                 int add)
    1733             : {
    1734         553 :         return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
    1735          79 :                                        peer->capability,
    1736          79 :                                        peer->supp_rates, peer->supp_rates_len,
    1737          79 :                                        peer->ht_capabilities,
    1738          79 :                                        peer->vht_capabilities,
    1739         158 :                                        peer->qos_info, peer->wmm_capable,
    1740          79 :                                        peer->ext_capab, peer->ext_capab_len,
    1741          79 :                                        peer->supp_channels,
    1742             :                                        peer->supp_channels_len,
    1743          79 :                                        peer->supp_oper_classes,
    1744             :                                        peer->supp_oper_classes_len);
    1745             : }
    1746             : 
    1747             : 
    1748          32 : static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
    1749             :                                    const u8 *buf, size_t len)
    1750             : {
    1751             :         struct wpa_tdls_peer *peer;
    1752             :         struct wpa_eapol_ie_parse kde;
    1753             :         struct wpa_ie_data ie;
    1754             :         int cipher;
    1755             :         const u8 *cpos;
    1756          32 :         struct wpa_tdls_ftie *ftie = NULL;
    1757             :         struct wpa_tdls_timeoutie *timeoutie;
    1758             :         struct wpa_tdls_lnkid *lnkid;
    1759          32 :         u32 lifetime = 0;
    1760             : #if 0
    1761             :         struct rsn_ie_hdr *hdr;
    1762             :         u8 *pos;
    1763             :         u16 rsn_capab;
    1764             :         u16 rsn_ver;
    1765             : #endif
    1766             :         u8 dtoken;
    1767             :         u16 ielen;
    1768          32 :         u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
    1769          32 :         int tdls_prohibited = sm->tdls_prohibited;
    1770          32 :         int existing_peer = 0;
    1771             : 
    1772          32 :         if (len < 3 + 3)
    1773           0 :                 return -1;
    1774             : 
    1775          32 :         cpos = buf;
    1776          32 :         cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
    1777             : 
    1778             :         /* driver had already verified the frame format */
    1779          32 :         dtoken = *cpos++; /* dialog token */
    1780             : 
    1781          32 :         wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
    1782             : 
    1783          32 :         peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer);
    1784          32 :         if (peer == NULL)
    1785           0 :                 goto error;
    1786             : 
    1787             :         /* If found, use existing entry instead of adding a new one;
    1788             :          * how to handle the case where both ends initiate at the
    1789             :          * same time? */
    1790          32 :         if (existing_peer) {
    1791           3 :                 if (peer->tpk_success) {
    1792           0 :                         wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
    1793             :                                    "direct link is enabled - tear down the "
    1794             :                                    "old link first");
    1795           0 :                         wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
    1796           0 :                         wpa_tdls_peer_clear(sm, peer);
    1797           3 :                 } else if (peer->initiator) {
    1798             :                         /*
    1799             :                          * An entry is already present, so check if we already
    1800             :                          * sent a TDLS Setup Request. If so, compare MAC
    1801             :                          * addresses and let the STA with the lower MAC address
    1802             :                          * continue as the initiator. The other negotiation is
    1803             :                          * terminated.
    1804             :                          */
    1805           2 :                         if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
    1806           6 :                                 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
    1807             :                                            "from peer with higher address "
    1808           6 :                                            MACSTR, MAC2STR(src_addr));
    1809           1 :                                 return -1;
    1810             :                         } else {
    1811           6 :                                 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
    1812             :                                            "from peer with lower address "
    1813             :                                            MACSTR " (terminate previously "
    1814             :                                            "initiated negotiation",
    1815           6 :                                            MAC2STR(src_addr));
    1816           1 :                                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
    1817           1 :                                                  peer->addr);
    1818           1 :                                 wpa_tdls_peer_clear(sm, peer);
    1819             :                         }
    1820             :                 }
    1821             :         }
    1822             : 
    1823             :         /* capability information */
    1824          31 :         peer->capability = WPA_GET_LE16(cpos);
    1825          31 :         cpos += 2;
    1826             : 
    1827          31 :         ielen = len - (cpos - buf); /* start of IE in buf */
    1828             : 
    1829             :         /*
    1830             :          * Don't reject the message if failing to parse IEs. The IEs we need are
    1831             :          * explicitly checked below. Some APs may add arbitrary padding to the
    1832             :          * end of short TDLS frames and that would look like invalid IEs.
    1833             :          */
    1834          31 :         if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0)
    1835           0 :                 wpa_printf(MSG_DEBUG,
    1836             :                            "TDLS: Failed to parse IEs in TPK M1 - ignore as an interop workaround");
    1837             : 
    1838          31 :         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
    1839           0 :                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
    1840             :                            "TPK M1");
    1841           0 :                 goto error;
    1842             :         }
    1843          62 :         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
    1844          31 :                     kde.lnkid, kde.lnkid_len);
    1845          31 :         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
    1846          31 :         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
    1847           1 :                 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
    1848           1 :                 status = WLAN_STATUS_REQUEST_DECLINED;
    1849           1 :                 goto error;
    1850             :         }
    1851             : 
    1852         180 :         wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
    1853         180 :                    MAC2STR(src_addr));
    1854             : 
    1855          30 :         if (copy_supp_rates(&kde, peer) < 0)
    1856           0 :                 goto error;
    1857             : 
    1858          30 :         if (copy_peer_ht_capab(&kde, peer) < 0)
    1859           0 :                 goto error;
    1860             : 
    1861          30 :         if (copy_peer_vht_capab(&kde, peer) < 0)
    1862           0 :                 goto error;
    1863             : 
    1864          30 :         if (copy_peer_ext_capab(&kde, peer) < 0)
    1865           0 :                 goto error;
    1866             : 
    1867          30 :         if (copy_peer_supp_channels(&kde, peer) < 0)
    1868           0 :                 goto error;
    1869             : 
    1870          30 :         if (copy_peer_supp_oper_classes(&kde, peer) < 0)
    1871           0 :                 goto error;
    1872             : 
    1873          30 :         peer->qos_info = kde.qosinfo;
    1874             : 
    1875             :         /* Overwrite with the qos_info obtained in WMM IE */
    1876          30 :         if (copy_peer_wmm_capab(&kde, peer) < 0)
    1877           0 :                 goto error;
    1878             : 
    1879          30 :         peer->aid = kde.aid;
    1880             : 
    1881             : #ifdef CONFIG_TDLS_TESTING
    1882          30 :         if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
    1883           2 :                 peer = wpa_tdls_add_peer(sm, src_addr, NULL);
    1884           2 :                 if (peer == NULL)
    1885           0 :                         goto error;
    1886           2 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
    1887             :                            "TDLS setup - send own request");
    1888           2 :                 peer->initiator = 1;
    1889           2 :                 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
    1890             :                                         NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
    1891           2 :                 wpa_tdls_send_tpk_m1(sm, peer);
    1892             :         }
    1893             : 
    1894          30 :         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
    1895             :             tdls_prohibited) {
    1896           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
    1897             :                            "on TDLS");
    1898           0 :                 tdls_prohibited = 0;
    1899             :         }
    1900             : #endif /* CONFIG_TDLS_TESTING */
    1901             : 
    1902          30 :         if (tdls_prohibited) {
    1903           0 :                 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
    1904           0 :                 status = WLAN_STATUS_REQUEST_DECLINED;
    1905           0 :                 goto error;
    1906             :         }
    1907             : 
    1908          30 :         if (!wpa_tdls_get_privacy(sm)) {
    1909           6 :                 if (kde.rsn_ie) {
    1910           0 :                         wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
    1911             :                                    "security is disabled");
    1912           0 :                         status = WLAN_STATUS_SECURITY_DISABLED;
    1913           0 :                         goto error;
    1914             :                 }
    1915           6 :                 goto skip_rsn;
    1916             :         }
    1917             : 
    1918          48 :         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
    1919          24 :             kde.rsn_ie == NULL) {
    1920           0 :                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
    1921           0 :                 status = WLAN_STATUS_INVALID_PARAMETERS;
    1922           0 :                 goto error;
    1923             :         }
    1924             : 
    1925          24 :         if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
    1926           0 :                 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
    1927             :                            "TPK M1");
    1928           0 :                 status = WLAN_STATUS_INVALID_RSNIE;
    1929           0 :                 goto error;
    1930             :         }
    1931             : 
    1932          24 :         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
    1933           0 :                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
    1934           0 :                 status = WLAN_STATUS_INVALID_RSNIE;
    1935           0 :                 goto error;
    1936             :         }
    1937             : 
    1938          24 :         cipher = ie.pairwise_cipher;
    1939          24 :         if (cipher & WPA_CIPHER_CCMP) {
    1940          24 :                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
    1941          24 :                 cipher = WPA_CIPHER_CCMP;
    1942             :         } else {
    1943           0 :                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
    1944           0 :                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
    1945           0 :                 goto error;
    1946             :         }
    1947             : 
    1948          24 :         if ((ie.capabilities &
    1949             :              (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
    1950             :             WPA_CAPABILITY_PEERKEY_ENABLED) {
    1951           0 :                 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
    1952             :                            "TPK M1");
    1953           0 :                 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
    1954           0 :                 goto error;
    1955             :         }
    1956             : 
    1957             :         /* Lifetime */
    1958          24 :         if (kde.key_lifetime == NULL) {
    1959           0 :                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
    1960           0 :                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
    1961           0 :                 goto error;
    1962             :         }
    1963          24 :         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
    1964          24 :         lifetime = WPA_GET_LE32(timeoutie->value);
    1965          24 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
    1966          24 :         if (lifetime < 300) {
    1967           0 :                 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
    1968           0 :                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
    1969           0 :                 goto error;
    1970             :         }
    1971             : 
    1972             : skip_rsn:
    1973             : #ifdef CONFIG_TDLS_TESTING
    1974          30 :         if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
    1975           2 :                 if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) {
    1976             :                         /*
    1977             :                          * The request frame from us is going to win, so do not
    1978             :                          * replace information based on this request frame from
    1979             :                          * the peer.
    1980             :                          */
    1981           1 :                         goto skip_rsn_check;
    1982             :                 }
    1983             :         }
    1984             : #endif /* CONFIG_TDLS_TESTING */
    1985             : 
    1986          29 :         peer->initiator = 0; /* Need to check */
    1987          29 :         peer->dtoken = dtoken;
    1988             : 
    1989          29 :         if (!wpa_tdls_get_privacy(sm)) {
    1990           6 :                 peer->rsnie_i_len = 0;
    1991           6 :                 peer->rsnie_p_len = 0;
    1992           6 :                 peer->cipher = WPA_CIPHER_NONE;
    1993           6 :                 goto skip_rsn_check;
    1994             :         }
    1995             : 
    1996          23 :         ftie = (struct wpa_tdls_ftie *) kde.ftie;
    1997          23 :         os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
    1998          23 :         peer->rsnie_i_len = kde.rsn_ie_len;
    1999          23 :         peer->cipher = cipher;
    2000             : 
    2001          23 :         if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
    2002             :                 /*
    2003             :                  * There is no point in updating the RNonce for every obtained
    2004             :                  * TPK M1 frame (e.g., retransmission due to timeout) with the
    2005             :                  * same INonce (SNonce in FTIE). However, if the TPK M1 is
    2006             :                  * retransmitted with a different INonce, update the RNonce
    2007             :                  * since this is for a new TDLS session.
    2008             :                  */
    2009          23 :                 wpa_printf(MSG_DEBUG,
    2010             :                            "TDLS: New TPK M1 INonce - generate new RNonce");
    2011          23 :                 os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
    2012          23 :                 if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
    2013           0 :                         wpa_msg(sm->ctx->ctx, MSG_WARNING,
    2014             :                                 "TDLS: Failed to get random data for responder nonce");
    2015           0 :                         goto error;
    2016             :                 }
    2017             :         }
    2018             : 
    2019             : #if 0
    2020             :         /* get version info from RSNIE received from Peer */
    2021             :         hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
    2022             :         rsn_ver = WPA_GET_LE16(hdr->version);
    2023             : 
    2024             :         /* use min(peer's version, out version) */
    2025             :         if (rsn_ver > RSN_VERSION)
    2026             :                 rsn_ver = RSN_VERSION;
    2027             : 
    2028             :         hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
    2029             : 
    2030             :         hdr->elem_id = WLAN_EID_RSN;
    2031             :         WPA_PUT_LE16(hdr->version, rsn_ver);
    2032             :         pos = (u8 *) (hdr + 1);
    2033             : 
    2034             :         RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
    2035             :         pos += RSN_SELECTOR_LEN;
    2036             :         /* Include only the selected cipher in pairwise cipher suite */
    2037             :         WPA_PUT_LE16(pos, 1);
    2038             :         pos += 2;
    2039             :         if (cipher == WPA_CIPHER_CCMP)
    2040             :                 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
    2041             :         pos += RSN_SELECTOR_LEN;
    2042             : 
    2043             :         WPA_PUT_LE16(pos, 1);
    2044             :         pos += 2;
    2045             :         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
    2046             :         pos += RSN_SELECTOR_LEN;
    2047             : 
    2048             :         rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
    2049             :         rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
    2050             :         WPA_PUT_LE16(pos, rsn_capab);
    2051             :         pos += 2;
    2052             : 
    2053             :         hdr->len = (pos - peer->rsnie_p) - 2;
    2054             :         peer->rsnie_p_len = pos - peer->rsnie_p;
    2055             : #endif
    2056             : 
    2057             :         /* temp fix: validation of RSNIE later */
    2058          23 :         os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
    2059          23 :         peer->rsnie_p_len = peer->rsnie_i_len;
    2060             : 
    2061          46 :         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
    2062          23 :                     peer->rsnie_p, peer->rsnie_p_len);
    2063             : 
    2064          23 :         peer->lifetime = lifetime;
    2065             : 
    2066          23 :         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
    2067             : 
    2068             : skip_rsn_check:
    2069             : #ifdef CONFIG_TDLS_TESTING
    2070          30 :         if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
    2071           2 :                 goto skip_add_peer;
    2072             : #endif /* CONFIG_TDLS_TESTING */
    2073             : 
    2074             :         /* add supported rates, capabilities, and qos_info to the TDLS peer */
    2075          28 :         if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
    2076           0 :                 goto error;
    2077             : 
    2078             : #ifdef CONFIG_TDLS_TESTING
    2079             : skip_add_peer:
    2080             : #endif /* CONFIG_TDLS_TESTING */
    2081          30 :         peer->tpk_in_progress = 1;
    2082             : 
    2083          30 :         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
    2084          30 :         if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
    2085           0 :                 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
    2086           0 :                 goto error;
    2087             :         }
    2088             : 
    2089          30 :         return 0;
    2090             : 
    2091             : error:
    2092           1 :         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
    2093             :                             status);
    2094           1 :         if (peer)
    2095           1 :                 wpa_tdls_peer_free(sm, peer);
    2096           1 :         return -1;
    2097             : }
    2098             : 
    2099             : 
    2100          51 : static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
    2101             : {
    2102          51 :         peer->tpk_success = 1;
    2103          51 :         peer->tpk_in_progress = 0;
    2104          51 :         eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
    2105          51 :         if (wpa_tdls_get_privacy(sm)) {
    2106          39 :                 u32 lifetime = peer->lifetime;
    2107             :                 /*
    2108             :                  * Start the initiator process a bit earlier to avoid race
    2109             :                  * condition with the responder sending teardown request.
    2110             :                  */
    2111          39 :                 if (lifetime > 3 && peer->initiator)
    2112          20 :                         lifetime -= 3;
    2113          39 :                 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
    2114             :                                        sm, peer);
    2115             : #ifdef CONFIG_TDLS_TESTING
    2116          39 :         if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
    2117           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
    2118             :                            "expiration");
    2119           0 :                 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
    2120             :         }
    2121             : #endif /* CONFIG_TDLS_TESTING */
    2122             :         }
    2123             : 
    2124          51 :         if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
    2125           0 :                 wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
    2126             :                            "driver");
    2127           0 :                 return -1;
    2128             :         }
    2129          51 :         peer->reconfig_key = 0;
    2130             : 
    2131          51 :         return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
    2132             : }
    2133             : 
    2134             : 
    2135          36 : static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
    2136             :                                    const u8 *buf, size_t len)
    2137             : {
    2138             :         struct wpa_tdls_peer *peer;
    2139             :         struct wpa_eapol_ie_parse kde;
    2140             :         struct wpa_ie_data ie;
    2141             :         int cipher;
    2142             :         struct wpa_tdls_ftie *ftie;
    2143             :         struct wpa_tdls_timeoutie *timeoutie;
    2144             :         struct wpa_tdls_lnkid *lnkid;
    2145             :         u32 lifetime;
    2146             :         u8 dtoken;
    2147             :         int ielen;
    2148             :         u16 status;
    2149             :         const u8 *pos;
    2150          36 :         int ret = 0;
    2151             : 
    2152         216 :         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
    2153         216 :                    "(Peer " MACSTR ")", MAC2STR(src_addr));
    2154          36 :         for (peer = sm->tdls; peer; peer = peer->next) {
    2155          34 :                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
    2156          34 :                         break;
    2157             :         }
    2158          36 :         if (peer == NULL) {
    2159          12 :                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
    2160          12 :                            "TPK M2: " MACSTR, MAC2STR(src_addr));
    2161           2 :                 return -1;
    2162             :         }
    2163          34 :         if (!peer->initiator) {
    2164             :                 /*
    2165             :                  * This may happen if both devices try to initiate TDLS at the
    2166             :                  * same time and we accept the TPK M1 from the peer in
    2167             :                  * wpa_tdls_process_tpk_m1() and clear our previous state.
    2168             :                  */
    2169          24 :                 wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so "
    2170          24 :                            "ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
    2171           4 :                 return -1;
    2172             :         }
    2173          30 :         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
    2174             : 
    2175          30 :         if (len < 3 + 2 + 1) {
    2176           0 :                 wpa_tdls_disable_peer_link(sm, peer);
    2177           0 :                 return -1;
    2178             :         }
    2179             : 
    2180          30 :         pos = buf;
    2181          30 :         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
    2182          30 :         status = WPA_GET_LE16(pos);
    2183          30 :         pos += 2 /* status code */;
    2184             : 
    2185          30 :         if (status != WLAN_STATUS_SUCCESS) {
    2186           1 :                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
    2187             :                            status);
    2188           1 :                 wpa_tdls_disable_peer_link(sm, peer);
    2189           1 :                 return -1;
    2190             :         }
    2191             : 
    2192          29 :         status = WLAN_STATUS_UNSPECIFIED_FAILURE;
    2193             : 
    2194             :         /* TODO: need to verify dialog token matches here or in kernel */
    2195          29 :         dtoken = *pos++; /* dialog token */
    2196             : 
    2197          29 :         wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
    2198             : 
    2199          29 :         if (len < 3 + 2 + 1 + 2) {
    2200           0 :                 wpa_tdls_disable_peer_link(sm, peer);
    2201           0 :                 return -1;
    2202             :         }
    2203             : 
    2204             :         /* capability information */
    2205          29 :         peer->capability = WPA_GET_LE16(pos);
    2206          29 :         pos += 2;
    2207             : 
    2208          29 :         ielen = len - (pos - buf); /* start of IE in buf */
    2209             : 
    2210             :         /*
    2211             :          * Don't reject the message if failing to parse IEs. The IEs we need are
    2212             :          * explicitly checked below. Some APs may add arbitrary padding to the
    2213             :          * end of short TDLS frames and that would look like invalid IEs.
    2214             :          */
    2215          29 :         if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0)
    2216           0 :                 wpa_printf(MSG_DEBUG,
    2217             :                            "TDLS: Failed to parse IEs in TPK M2 - ignore as an interop workaround");
    2218             : 
    2219             : #ifdef CONFIG_TDLS_TESTING
    2220          29 :         if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
    2221           1 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
    2222           1 :                 status = WLAN_STATUS_REQUEST_DECLINED;
    2223           1 :                 goto error;
    2224             :         }
    2225             : #endif /* CONFIG_TDLS_TESTING */
    2226             : 
    2227          28 :         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
    2228           0 :                 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
    2229             :                            "TPK M2");
    2230           0 :                 goto error;
    2231             :         }
    2232          56 :         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
    2233          28 :                     kde.lnkid, kde.lnkid_len);
    2234          28 :         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
    2235             : 
    2236          28 :         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
    2237           0 :                 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
    2238           0 :                 status = WLAN_STATUS_NOT_IN_SAME_BSS;
    2239           0 :                 goto error;
    2240             :         }
    2241             : 
    2242          28 :         if (copy_supp_rates(&kde, peer) < 0)
    2243           0 :                 goto error;
    2244             : 
    2245          28 :         if (copy_peer_ht_capab(&kde, peer) < 0)
    2246           0 :                 goto error;
    2247             : 
    2248          28 :         if (copy_peer_vht_capab(&kde, peer) < 0)
    2249           0 :                 goto error;
    2250             : 
    2251          28 :         if (copy_peer_ext_capab(&kde, peer) < 0)
    2252           0 :                 goto error;
    2253             : 
    2254          28 :         if (copy_peer_supp_channels(&kde, peer) < 0)
    2255           0 :                 goto error;
    2256             : 
    2257          28 :         if (copy_peer_supp_oper_classes(&kde, peer) < 0)
    2258           0 :                 goto error;
    2259             : 
    2260          28 :         peer->qos_info = kde.qosinfo;
    2261             : 
    2262             :         /* Overwrite with the qos_info obtained in WMM IE */
    2263          28 :         if (copy_peer_wmm_capab(&kde, peer) < 0)
    2264           0 :                 goto error;
    2265             : 
    2266          28 :         peer->aid = kde.aid;
    2267             : 
    2268          28 :         if (!wpa_tdls_get_privacy(sm)) {
    2269           6 :                 peer->rsnie_p_len = 0;
    2270           6 :                 peer->cipher = WPA_CIPHER_NONE;
    2271           6 :                 goto skip_rsn;
    2272             :         }
    2273             : 
    2274          44 :         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
    2275          22 :             kde.rsn_ie == NULL) {
    2276           0 :                 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
    2277           0 :                 status = WLAN_STATUS_INVALID_PARAMETERS;
    2278           0 :                 goto error;
    2279             :         }
    2280          44 :         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
    2281          22 :                     kde.rsn_ie, kde.rsn_ie_len);
    2282             : 
    2283          22 :         if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
    2284           0 :                 wpa_printf(MSG_INFO,
    2285             :                            "TDLS: Too long Responder RSN IE in TPK M2");
    2286           0 :                 status = WLAN_STATUS_INVALID_RSNIE;
    2287           0 :                 goto error;
    2288             :         }
    2289             : 
    2290             :         /*
    2291             :          * FIX: bitwise comparison of RSN IE is not the correct way of
    2292             :          * validation this. It can be different, but certain fields must
    2293             :          * match. Since we list only a single pairwise cipher in TPK M1, the
    2294             :          * memcmp is likely to work in most cases, though.
    2295             :          */
    2296          44 :         if (kde.rsn_ie_len != peer->rsnie_i_len ||
    2297          22 :             os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
    2298           0 :                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
    2299             :                            "not match with RSN IE used in TPK M1");
    2300           0 :                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
    2301           0 :                             peer->rsnie_i, peer->rsnie_i_len);
    2302           0 :                 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
    2303           0 :                             kde.rsn_ie, kde.rsn_ie_len);
    2304           0 :                 status = WLAN_STATUS_INVALID_RSNIE;
    2305           0 :                 goto error;
    2306             :         }
    2307             : 
    2308          22 :         if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
    2309           0 :                 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
    2310           0 :                 status = WLAN_STATUS_INVALID_RSNIE;
    2311           0 :                 goto error;
    2312             :         }
    2313             : 
    2314          22 :         cipher = ie.pairwise_cipher;
    2315          22 :         if (cipher == WPA_CIPHER_CCMP) {
    2316          22 :                 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
    2317          22 :                 cipher = WPA_CIPHER_CCMP;
    2318             :         } else {
    2319           0 :                 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
    2320           0 :                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
    2321           0 :                 goto error;
    2322             :         }
    2323             : 
    2324          22 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
    2325          22 :                     kde.ftie, sizeof(*ftie));
    2326          22 :         ftie = (struct wpa_tdls_ftie *) kde.ftie;
    2327             : 
    2328          22 :         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
    2329           0 :                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
    2330             :                            "not match with FTIE SNonce used in TPK M1");
    2331             :                 /* Silently discard the frame */
    2332           0 :                 return -1;
    2333             :         }
    2334             : 
    2335             :         /* Responder Nonce and RSN IE */
    2336          22 :         os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
    2337          22 :         os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
    2338          22 :         peer->rsnie_p_len = kde.rsn_ie_len;
    2339          22 :         peer->cipher = cipher;
    2340             : 
    2341             :         /* Lifetime */
    2342          22 :         if (kde.key_lifetime == NULL) {
    2343           0 :                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
    2344           0 :                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
    2345           0 :                 goto error;
    2346             :         }
    2347          22 :         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
    2348          22 :         lifetime = WPA_GET_LE32(timeoutie->value);
    2349          22 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
    2350             :                    lifetime);
    2351          22 :         if (lifetime != peer->lifetime) {
    2352           1 :                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
    2353             :                            "TPK M2 (expected %u)", lifetime, peer->lifetime);
    2354           1 :                 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
    2355           1 :                 goto error;
    2356             :         }
    2357             : 
    2358          21 :         wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
    2359             : 
    2360             :         /* Process MIC check to see if TPK M2 is right */
    2361          21 :         if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid,
    2362             :                                            (u8 *) timeoutie, ftie) < 0) {
    2363             :                 /* Discard the frame */
    2364           1 :                 wpa_tdls_del_key(sm, peer);
    2365           1 :                 wpa_tdls_disable_peer_link(sm, peer);
    2366           1 :                 return -1;
    2367             :         }
    2368             : 
    2369          20 :         if (wpa_tdls_set_key(sm, peer) < 0) {
    2370             :                 /*
    2371             :                  * Some drivers may not be able to config the key prior to full
    2372             :                  * STA entry having been configured.
    2373             :                  */
    2374          20 :                 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
    2375             :                            "STA entry is complete");
    2376          20 :                 peer->reconfig_key = 1;
    2377             :         }
    2378             : 
    2379             : skip_rsn:
    2380          26 :         peer->dtoken = dtoken;
    2381             : 
    2382             :         /* add supported rates, capabilities, and qos_info to the TDLS peer */
    2383          26 :         if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
    2384           0 :                 goto error;
    2385             : 
    2386          26 :         wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
    2387             :                    "TPK Handshake Message 3");
    2388          26 :         if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
    2389           0 :                 goto error;
    2390             : 
    2391          26 :         if (!peer->tpk_success) {
    2392             :                 /*
    2393             :                  * Enable Link only when tpk_success is 0, signifying that this
    2394             :                  * processing of TPK M2 frame is not because of a retransmission
    2395             :                  * during TDLS setup handshake.
    2396             :                  */
    2397          26 :                 ret = wpa_tdls_enable_link(sm, peer);
    2398          26 :                 if (ret < 0) {
    2399           0 :                         wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
    2400           0 :                         wpa_tdls_do_teardown(
    2401             :                                 sm, peer,
    2402             :                                 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    2403             :                 }
    2404             :         }
    2405          26 :         return ret;
    2406             : 
    2407             : error:
    2408           2 :         wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
    2409             :                             status);
    2410           2 :         wpa_tdls_disable_peer_link(sm, peer);
    2411           2 :         return -1;
    2412             : }
    2413             : 
    2414             : 
    2415          28 : static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
    2416             :                                    const u8 *buf, size_t len)
    2417             : {
    2418             :         struct wpa_tdls_peer *peer;
    2419             :         struct wpa_eapol_ie_parse kde;
    2420             :         struct wpa_tdls_ftie *ftie;
    2421             :         struct wpa_tdls_timeoutie *timeoutie;
    2422             :         struct wpa_tdls_lnkid *lnkid;
    2423             :         int ielen;
    2424             :         u16 status;
    2425             :         const u8 *pos;
    2426             :         u32 lifetime;
    2427          28 :         int ret = 0;
    2428             : 
    2429         168 :         wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
    2430         168 :                    "(Peer " MACSTR ")", MAC2STR(src_addr));
    2431          28 :         for (peer = sm->tdls; peer; peer = peer->next) {
    2432          28 :                 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
    2433          28 :                         break;
    2434             :         }
    2435          28 :         if (peer == NULL) {
    2436           0 :                 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
    2437           0 :                            "TPK M3: " MACSTR, MAC2STR(src_addr));
    2438           0 :                 return -1;
    2439             :         }
    2440          28 :         wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
    2441             : 
    2442          28 :         if (len < 3 + 3)
    2443           0 :                 goto error;
    2444          28 :         pos = buf;
    2445          28 :         pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
    2446             : 
    2447          28 :         status = WPA_GET_LE16(pos);
    2448             : 
    2449          28 :         if (status != 0) {
    2450           2 :                 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
    2451             :                            status);
    2452           2 :                 goto error;
    2453             :         }
    2454          26 :         pos += 2 /* status code */ + 1 /* dialog token */;
    2455             : 
    2456          26 :         ielen = len - (pos - buf); /* start of IE in buf */
    2457             : 
    2458             :         /*
    2459             :          * Don't reject the message if failing to parse IEs. The IEs we need are
    2460             :          * explicitly checked below. Some APs piggy-back broken IEs to the end
    2461             :          * of a TDLS Confirm packet, which will fail the link if we don't ignore
    2462             :          * this error.
    2463             :          */
    2464          26 :         if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
    2465           0 :                 wpa_printf(MSG_DEBUG,
    2466             :                            "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround");
    2467             :         }
    2468             : 
    2469          26 :         if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
    2470           0 :                 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
    2471           0 :                 goto error;
    2472             :         }
    2473          52 :         wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
    2474          26 :                     (u8 *) kde.lnkid, kde.lnkid_len);
    2475          26 :         lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
    2476             : 
    2477          26 :         if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
    2478           0 :                 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
    2479           0 :                 goto error;
    2480             :         }
    2481             : 
    2482          26 :         if (!wpa_tdls_get_privacy(sm))
    2483           6 :                 goto skip_rsn;
    2484             : 
    2485          20 :         if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
    2486           0 :                 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
    2487           0 :                 goto error;
    2488             :         }
    2489          20 :         wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
    2490          20 :                     kde.ftie, sizeof(*ftie));
    2491          20 :         ftie = (struct wpa_tdls_ftie *) kde.ftie;
    2492             : 
    2493          20 :         if (kde.rsn_ie == NULL) {
    2494           0 :                 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
    2495           0 :                 goto error;
    2496             :         }
    2497          40 :         wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
    2498          20 :                     kde.rsn_ie, kde.rsn_ie_len);
    2499          40 :         if (kde.rsn_ie_len != peer->rsnie_p_len ||
    2500          20 :             os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
    2501           0 :                 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
    2502             :                            "with the one sent in TPK M2");
    2503           0 :                 goto error;
    2504             :         }
    2505             : 
    2506          20 :         if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
    2507           0 :                 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
    2508             :                            "not match with FTIE ANonce used in TPK M2");
    2509           0 :                 goto error;
    2510             :         }
    2511             : 
    2512          20 :         if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
    2513           0 :                 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
    2514             :                            "match with FTIE SNonce used in TPK M1");
    2515           0 :                 goto error;
    2516             :         }
    2517             : 
    2518          20 :         if (kde.key_lifetime == NULL) {
    2519           0 :                 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
    2520           0 :                 goto error;
    2521             :         }
    2522          20 :         timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
    2523          20 :         wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
    2524             :                     (u8 *) timeoutie, sizeof(*timeoutie));
    2525          20 :         lifetime = WPA_GET_LE32(timeoutie->value);
    2526          20 :         wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
    2527             :                    lifetime);
    2528          20 :         if (lifetime != peer->lifetime) {
    2529           0 :                 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
    2530             :                            "TPK M3 (expected %u)", lifetime, peer->lifetime);
    2531           0 :                 goto error;
    2532             :         }
    2533             : 
    2534          20 :         if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid,
    2535             :                                            (u8 *) timeoutie, ftie) < 0) {
    2536           1 :                 wpa_tdls_del_key(sm, peer);
    2537           1 :                 goto error;
    2538             :         }
    2539             : 
    2540          19 :         if (wpa_tdls_set_key(sm, peer) < 0) {
    2541             :                 /*
    2542             :                  * Some drivers may not be able to config the key prior to full
    2543             :                  * STA entry having been configured.
    2544             :                  */
    2545          19 :                 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
    2546             :                            "STA entry is complete");
    2547          19 :                 peer->reconfig_key = 1;
    2548             :         }
    2549             : 
    2550             : skip_rsn:
    2551             :         /* add supported rates, capabilities, and qos_info to the TDLS peer */
    2552          25 :         if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
    2553           0 :                 goto error;
    2554             : 
    2555          25 :         if (!peer->tpk_success) {
    2556             :                 /*
    2557             :                  * Enable Link only when tpk_success is 0, signifying that this
    2558             :                  * processing of TPK M3 frame is not because of a retransmission
    2559             :                  * during TDLS setup handshake.
    2560             :                  */
    2561          25 :                 ret = wpa_tdls_enable_link(sm, peer);
    2562          25 :                 if (ret < 0) {
    2563           0 :                         wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
    2564           0 :                         goto error;
    2565             :                 }
    2566             :         }
    2567          25 :         return ret;
    2568             : error:
    2569           3 :         wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    2570           3 :         return -1;
    2571             : }
    2572             : 
    2573             : 
    2574          71 : static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
    2575             : {
    2576          71 :         struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
    2577             : 
    2578          71 :         os_memset(lifetime, 0, ie_len);
    2579          71 :         lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
    2580          71 :         lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
    2581          71 :         lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
    2582          71 :         WPA_PUT_LE32(lifetime->value, tsecs);
    2583          71 :         os_memcpy(pos, ie, ie_len);
    2584          71 :         return pos + ie_len;
    2585             : }
    2586             : 
    2587             : 
    2588             : /**
    2589             :  * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
    2590             :  * @sm: Pointer to WPA state machine data from wpa_sm_init()
    2591             :  * @peer: MAC address of the peer STA
    2592             :  * Returns: 0 on success, or -1 on failure
    2593             :  *
    2594             :  * Send TPK Handshake Message 1 info to driver to start TDLS
    2595             :  * handshake with the peer.
    2596             :  */
    2597          31 : int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
    2598             : {
    2599             :         struct wpa_tdls_peer *peer;
    2600          31 :         int tdls_prohibited = sm->tdls_prohibited;
    2601             : 
    2602          31 :         if (sm->tdls_disabled || !sm->tdls_supported)
    2603           0 :                 return -1;
    2604             : 
    2605             : #ifdef CONFIG_TDLS_TESTING
    2606          31 :         if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
    2607             :             tdls_prohibited) {
    2608           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
    2609             :                            "on TDLS");
    2610           0 :                 tdls_prohibited = 0;
    2611             :         }
    2612             : #endif /* CONFIG_TDLS_TESTING */
    2613             : 
    2614          31 :         if (tdls_prohibited) {
    2615           0 :                 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
    2616             :                            "reject request to start setup");
    2617           0 :                 return -1;
    2618             :         }
    2619             : 
    2620          31 :         peer = wpa_tdls_add_peer(sm, addr, NULL);
    2621          31 :         if (peer == NULL)
    2622           1 :                 return -1;
    2623             : 
    2624          30 :         if (peer->tpk_in_progress) {
    2625           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer");
    2626           0 :                 return 0;
    2627             :         }
    2628             : 
    2629          30 :         peer->initiator = 1;
    2630             : 
    2631             :         /* add the peer to the driver as a "setup in progress" peer */
    2632          30 :         if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
    2633             :                                     NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
    2634           0 :                 wpa_tdls_disable_peer_link(sm, peer);
    2635           0 :                 return -1;
    2636             :         }
    2637             : 
    2638          30 :         peer->tpk_in_progress = 1;
    2639             : 
    2640          30 :         if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
    2641           0 :                 wpa_tdls_disable_peer_link(sm, peer);
    2642           0 :                 return -1;
    2643             :         }
    2644             : 
    2645          30 :         return 0;
    2646             : }
    2647             : 
    2648             : 
    2649          31 : void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr)
    2650             : {
    2651             :         struct wpa_tdls_peer *peer;
    2652             : 
    2653          31 :         if (sm->tdls_disabled || !sm->tdls_supported)
    2654           0 :                 return;
    2655             : 
    2656          31 :         for (peer = sm->tdls; peer; peer = peer->next) {
    2657           1 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
    2658           1 :                         break;
    2659             :         }
    2660             : 
    2661          31 :         if (peer == NULL || !peer->tpk_success)
    2662          30 :                 return;
    2663             : 
    2664           1 :         if (sm->tdls_external_setup) {
    2665             :                 /*
    2666             :                  * Disable previous link to allow renegotiation to be completed
    2667             :                  * on AP path.
    2668             :                  */
    2669           1 :                 wpa_tdls_do_teardown(sm, peer,
    2670             :                                      WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
    2671             :         }
    2672             : }
    2673             : 
    2674             : 
    2675             : /**
    2676             :  * wpa_supplicant_rx_tdls - Receive TDLS data frame
    2677             :  *
    2678             :  * This function is called to receive TDLS (ethertype = 0x890d) data frames.
    2679             :  */
    2680         127 : static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
    2681             :                                    const u8 *buf, size_t len)
    2682             : {
    2683         127 :         struct wpa_sm *sm = ctx;
    2684             :         struct wpa_tdls_frame *tf;
    2685             : 
    2686         127 :         wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
    2687             :                     buf, len);
    2688             : 
    2689         127 :         if (sm->tdls_disabled || !sm->tdls_supported) {
    2690           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
    2691             :                            "or unsupported by driver");
    2692           0 :                 return;
    2693             :         }
    2694             : 
    2695         127 :         if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
    2696           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
    2697           0 :                 return;
    2698             :         }
    2699             : 
    2700         127 :         if (len < sizeof(*tf)) {
    2701           0 :                 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
    2702           0 :                 return;
    2703             :         }
    2704             : 
    2705             :         /* Check to make sure its a valid encapsulated TDLS frame */
    2706         127 :         tf = (struct wpa_tdls_frame *) buf;
    2707         254 :         if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
    2708         127 :             tf->category != WLAN_ACTION_TDLS) {
    2709           0 :                 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
    2710             :                            "category=%u action=%u",
    2711           0 :                            tf->payloadtype, tf->category, tf->action);
    2712           0 :                 return;
    2713             :         }
    2714             : 
    2715         127 :         switch (tf->action) {
    2716             :         case WLAN_TDLS_SETUP_REQUEST:
    2717          32 :                 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
    2718          32 :                 break;
    2719             :         case WLAN_TDLS_SETUP_RESPONSE:
    2720          36 :                 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
    2721          36 :                 break;
    2722             :         case WLAN_TDLS_SETUP_CONFIRM:
    2723          28 :                 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
    2724          28 :                 break;
    2725             :         case WLAN_TDLS_TEARDOWN:
    2726          29 :                 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
    2727          29 :                 break;
    2728             :         case WLAN_TDLS_DISCOVERY_REQUEST:
    2729           2 :                 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
    2730           2 :                 break;
    2731             :         default:
    2732             :                 /* Kernel code will process remaining frames */
    2733           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
    2734           0 :                            tf->action);
    2735           0 :                 break;
    2736             :         }
    2737             : }
    2738             : 
    2739             : 
    2740             : /**
    2741             :  * wpa_tdls_init - Initialize driver interface parameters for TDLS
    2742             :  * @wpa_s: Pointer to wpa_supplicant data
    2743             :  * Returns: 0 on success, -1 on failure
    2744             :  *
    2745             :  * This function is called to initialize driver interface parameters for TDLS.
    2746             :  * wpa_drv_init() must have been called before this function to initialize the
    2747             :  * driver interface.
    2748             :  */
    2749         577 : int wpa_tdls_init(struct wpa_sm *sm)
    2750             : {
    2751         577 :         if (sm == NULL)
    2752           0 :                 return -1;
    2753             : 
    2754         577 :         sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname :
    2755             :                                      sm->ifname,
    2756         577 :                                      sm->own_addr,
    2757             :                                      ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
    2758             :                                      sm, 0);
    2759         577 :         if (sm->l2_tdls == NULL) {
    2760           1 :                 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
    2761             :                            "connection");
    2762           1 :                 return -1;
    2763             :         }
    2764             : 
    2765             :         /*
    2766             :          * Drivers that support TDLS but don't implement the get_capa callback
    2767             :          * are assumed to perform everything internally
    2768             :          */
    2769         576 :         if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
    2770             :                                  &sm->tdls_external_setup,
    2771             :                                  &sm->tdls_chan_switch) < 0) {
    2772          44 :                 sm->tdls_supported = 1;
    2773          44 :                 sm->tdls_external_setup = 0;
    2774             :         }
    2775             : 
    2776         576 :         wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
    2777         576 :                    "driver", sm->tdls_supported ? "" : " not");
    2778         576 :         wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
    2779         576 :                    sm->tdls_external_setup ? "external" : "internal");
    2780         576 :         wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS channel switching",
    2781         576 :                    sm->tdls_chan_switch ? "supports" : "does not support");
    2782             : 
    2783         576 :         return 0;
    2784             : }
    2785             : 
    2786             : 
    2787        3562 : void wpa_tdls_teardown_peers(struct wpa_sm *sm)
    2788             : {
    2789             :         struct wpa_tdls_peer *peer, *tmp;
    2790             : 
    2791        3562 :         if (!sm)
    2792        3566 :                 return;
    2793        3558 :         peer = sm->tdls;
    2794             : 
    2795        3558 :         wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
    2796             : 
    2797        7131 :         while (peer) {
    2798          15 :                 tmp = peer->next;
    2799          90 :                 wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
    2800          90 :                            MAC2STR(peer->addr));
    2801          15 :                 if (sm->tdls_external_setup)
    2802          15 :                         wpa_tdls_do_teardown(sm, peer,
    2803             :                                              WLAN_REASON_DEAUTH_LEAVING);
    2804             :                 else
    2805           0 :                         wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
    2806             : 
    2807          15 :                 peer = tmp;
    2808             :         }
    2809             : }
    2810             : 
    2811             : 
    2812        7370 : static void wpa_tdls_remove_peers(struct wpa_sm *sm)
    2813             : {
    2814             :         struct wpa_tdls_peer *peer, *tmp;
    2815             : 
    2816        7370 :         peer = sm->tdls;
    2817             : 
    2818       14740 :         while (peer) {
    2819             :                 int res;
    2820           0 :                 tmp = peer->next;
    2821           0 :                 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
    2822           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
    2823           0 :                            MAC2STR(peer->addr), res);
    2824           0 :                 wpa_tdls_peer_free(sm, peer);
    2825           0 :                 peer = tmp;
    2826             :         }
    2827        7370 : }
    2828             : 
    2829             : 
    2830             : /**
    2831             :  * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
    2832             :  *
    2833             :  * This function is called to recover driver interface parameters for TDLS
    2834             :  * and frees resources allocated for it.
    2835             :  */
    2836         612 : void wpa_tdls_deinit(struct wpa_sm *sm)
    2837             : {
    2838         612 :         if (sm == NULL)
    2839         637 :                 return;
    2840             : 
    2841         587 :         if (sm->l2_tdls)
    2842         576 :                 l2_packet_deinit(sm->l2_tdls);
    2843         587 :         sm->l2_tdls = NULL;
    2844             : 
    2845         587 :         wpa_tdls_remove_peers(sm);
    2846             : }
    2847             : 
    2848             : 
    2849        3340 : void wpa_tdls_assoc(struct wpa_sm *sm)
    2850             : {
    2851        3340 :         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
    2852        3340 :         wpa_tdls_remove_peers(sm);
    2853        3340 : }
    2854             : 
    2855             : 
    2856        3443 : void wpa_tdls_disassoc(struct wpa_sm *sm)
    2857             : {
    2858        3443 :         wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
    2859        3443 :         wpa_tdls_remove_peers(sm);
    2860        3443 : }
    2861             : 
    2862             : 
    2863        6632 : static int wpa_tdls_prohibited(struct ieee802_11_elems *elems)
    2864             : {
    2865             :         /* bit 38 - TDLS Prohibited */
    2866        6632 :         return !!(elems->ext_capab[2 + 4] & 0x40);
    2867             : }
    2868             : 
    2869             : 
    2870        6632 : static int wpa_tdls_chan_switch_prohibited(struct ieee802_11_elems *elems)
    2871             : {
    2872             :         /* bit 39 - TDLS Channel Switch Prohibited */
    2873        6632 :         return !!(elems->ext_capab[2 + 4] & 0x80);
    2874             : }
    2875             : 
    2876             : 
    2877        3326 : void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
    2878             : {
    2879             :         struct ieee802_11_elems elems;
    2880             : 
    2881        3326 :         sm->tdls_prohibited = 0;
    2882        3326 :         sm->tdls_chan_switch_prohibited = 0;
    2883             : 
    2884        6652 :         if (ies == NULL ||
    2885        6652 :             ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed ||
    2886        6652 :             elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
    2887        3326 :                 return;
    2888             : 
    2889        3326 :         sm->tdls_prohibited = wpa_tdls_prohibited(&elems);
    2890        3326 :         wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
    2891        3326 :                    sm->tdls_prohibited ? "prohibited" : "allowed");
    2892        3326 :         sm->tdls_chan_switch_prohibited =
    2893        3326 :                 wpa_tdls_chan_switch_prohibited(&elems);
    2894        3326 :         wpa_printf(MSG_DEBUG, "TDLS: TDLS channel switch %s in the target BSS",
    2895        3326 :                    sm->tdls_chan_switch_prohibited ? "prohibited" : "allowed");
    2896             : }
    2897             : 
    2898             : 
    2899        3306 : void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
    2900             : {
    2901             :         struct ieee802_11_elems elems;
    2902             : 
    2903        6612 :         if (ies == NULL ||
    2904        6612 :             ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed ||
    2905        6612 :             elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
    2906        3306 :                 return;
    2907             : 
    2908        3306 :         if (!sm->tdls_prohibited && wpa_tdls_prohibited(&elems)) {
    2909           0 :                 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
    2910             :                            "(Re)Association Response IEs");
    2911           0 :                 sm->tdls_prohibited = 1;
    2912             :         }
    2913             : 
    2914        6612 :         if (!sm->tdls_chan_switch_prohibited &&
    2915        3306 :             wpa_tdls_chan_switch_prohibited(&elems)) {
    2916           0 :                 wpa_printf(MSG_DEBUG,
    2917             :                            "TDLS: TDLS channel switch prohibited based on (Re)Association Response IEs");
    2918           0 :                 sm->tdls_chan_switch_prohibited = 1;
    2919             :         }
    2920             : }
    2921             : 
    2922             : 
    2923        4871 : void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
    2924             : {
    2925        4871 :         wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
    2926        4871 :         sm->tdls_disabled = !enabled;
    2927        4871 : }
    2928             : 
    2929             : 
    2930          59 : int wpa_tdls_is_external_setup(struct wpa_sm *sm)
    2931             : {
    2932          59 :         return sm->tdls_external_setup;
    2933             : }
    2934             : 
    2935             : 
    2936           3 : int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr,
    2937             :                                 u8 oper_class,
    2938             :                                 struct hostapd_freq_params *freq_params)
    2939             : {
    2940             :         struct wpa_tdls_peer *peer;
    2941             :         int ret;
    2942             : 
    2943           3 :         if (sm->tdls_disabled || !sm->tdls_supported)
    2944           0 :                 return -1;
    2945             : 
    2946           3 :         if (!sm->tdls_chan_switch) {
    2947           0 :                 wpa_printf(MSG_DEBUG,
    2948             :                            "TDLS: Channel switching not supported by the driver");
    2949           0 :                 return -1;
    2950             :         }
    2951             : 
    2952           3 :         if (sm->tdls_chan_switch_prohibited) {
    2953           0 :                 wpa_printf(MSG_DEBUG,
    2954             :                            "TDLS: Channel switching is prohibited in this BSS - reject request to switch channel");
    2955           0 :                 return -1;
    2956             :         }
    2957             : 
    2958           3 :         for (peer = sm->tdls; peer; peer = peer->next) {
    2959           1 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
    2960           1 :                         break;
    2961             :         }
    2962             : 
    2963           3 :         if (peer == NULL || !peer->tpk_success) {
    2964          12 :                 wpa_printf(MSG_ERROR, "TDLS: Peer " MACSTR
    2965          12 :                            " not found for channel switching", MAC2STR(addr));
    2966           2 :                 return -1;
    2967             :         }
    2968             : 
    2969           1 :         if (peer->chan_switch_enabled) {
    2970           0 :                 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
    2971             :                            " already has channel switching enabled",
    2972           0 :                            MAC2STR(addr));
    2973           0 :                 return 0;
    2974             :         }
    2975             : 
    2976           1 :         ret = wpa_sm_tdls_enable_channel_switch(sm, peer->addr,
    2977             :                                                 oper_class, freq_params);
    2978           1 :         if (!ret)
    2979           1 :                 peer->chan_switch_enabled = 1;
    2980             : 
    2981           1 :         return ret;
    2982             : }
    2983             : 
    2984             : 
    2985           3 : int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr)
    2986             : {
    2987             :         struct wpa_tdls_peer *peer;
    2988             : 
    2989           3 :         if (sm->tdls_disabled || !sm->tdls_supported)
    2990           0 :                 return -1;
    2991             : 
    2992           3 :         for (peer = sm->tdls; peer; peer = peer->next) {
    2993           2 :                 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
    2994           2 :                         break;
    2995             :         }
    2996             : 
    2997           3 :         if (!peer || !peer->chan_switch_enabled) {
    2998          12 :                 wpa_printf(MSG_ERROR, "TDLS: Channel switching not enabled for "
    2999          12 :                            MACSTR, MAC2STR(addr));
    3000           2 :                 return -1;
    3001             :         }
    3002             : 
    3003             :         /* ignore the return value */
    3004           1 :         wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
    3005             : 
    3006           1 :         peer->chan_switch_enabled = 0;
    3007           1 :         return 0;
    3008             : }

Generated by: LCOV version 1.10