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

Generated by: LCOV version 1.10