TDLS: Decline Setup Request with status code 37 if BSSID does not match
[mech_eap.git] / src / rsn_supp / tdls.c
index 2a6ecc6..93ae143 100644 (file)
@@ -564,7 +564,7 @@ static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
                wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
                                  peer->rsnie_p, timeoutie, (u8 *) ftie,
                                  mic);
-               if (os_memcmp(mic, ftie->mic, 16) != 0) {
+               if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
                        wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
                                   "dropping packet");
                        wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
@@ -591,7 +591,7 @@ static int wpa_supplicant_verify_tdls_mic_teardown(
        if (peer->tpk_set) {
                wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
                                          dtoken, lnkid, (u8 *) ftie, mic);
-               if (os_memcmp(mic, ftie->mic, 16) != 0) {
+               if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
                        wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
                                   "dropping packet");
                        return -1;
@@ -1382,11 +1382,85 @@ static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
                                            struct wpa_tdls_peer *peer,
                                            u8 dialog_token)
 {
+       size_t buf_len = 0;
+       struct wpa_tdls_timeoutie timeoutie;
+       u16 rsn_capab;
+       u8 *rbuf, *pos, *count_pos;
+       u16 count;
+       struct rsn_ie_hdr *hdr;
+       int status;
+
        wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
                   "(peer " MACSTR ")", MAC2STR(peer->addr));
+       if (!wpa_tdls_get_privacy(sm))
+               goto skip_rsn_ies;
+
+       /* Filling RSN IE */
+       hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
+       hdr->elem_id = WLAN_EID_RSN;
+       WPA_PUT_LE16(hdr->version, RSN_VERSION);
+       pos = (u8 *) (hdr + 1);
+       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
+       pos += RSN_SELECTOR_LEN;
+       count_pos = pos;
+       pos += 2;
+       count = 0;
+
+       /*
+       * AES-CCMP is the default encryption preferred for TDLS, so
+       * RSN IE is filled only with CCMP cipher suite.
+       * Note: TKIP is not used to encrypt TDLS link.
+       *
+       * Regardless of the cipher used on the AP connection, select CCMP
+       * here.
+       */
+       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
+       pos += RSN_SELECTOR_LEN;
+       count++;
+       WPA_PUT_LE16(count_pos, count);
+       WPA_PUT_LE16(pos, 1);
+       pos += 2;
+       RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
+       pos += RSN_SELECTOR_LEN;
+
+       rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
+       rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
+       WPA_PUT_LE16(pos, rsn_capab);
+       pos += 2;
+       hdr->len = (pos - (u8 *) hdr) - 2;
+       peer->rsnie_i_len = pos - peer->rsnie_i;
+
+       wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
+                   (u8 *) hdr, hdr->len + 2);
+skip_rsn_ies:
+       buf_len = 0;
+       if (wpa_tdls_get_privacy(sm)) {
+               /* Peer RSN IE, Lifetime */
+               buf_len += peer->rsnie_i_len +
+                       sizeof(struct wpa_tdls_timeoutie);
+       }
+       rbuf = os_zalloc(buf_len + 1);
+       if (rbuf == NULL) {
+               wpa_tdls_peer_free(sm, peer);
+               return -1;
+       }
+       pos = rbuf;
+
+       if (!wpa_tdls_get_privacy(sm))
+               goto skip_ies;
+       /* Initiator RSN IE */
+       pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
+       /* Lifetime */
+       peer->lifetime = TPK_LIFETIME;
+       pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
+                                    sizeof(timeoutie), peer->lifetime);
+       wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
+skip_ies:
+       status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
+                                  dialog_token, 0, 0,  rbuf, pos - rbuf);
+       os_free(rbuf);
 
-       return wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
-                                dialog_token, 0, 0, NULL, 0);
+       return status;
 }
 
 
@@ -1631,6 +1705,23 @@ static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
 }
 
 
+static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
+                               int add)
+{
+       return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
+                                      peer->capability,
+                                      peer->supp_rates, peer->supp_rates_len,
+                                      peer->ht_capabilities,
+                                      peer->vht_capabilities,
+                                      peer->qos_info, peer->ext_capab,
+                                      peer->ext_capab_len,
+                                      peer->supp_channels,
+                                      peer->supp_channels_len,
+                                      peer->supp_oper_classes,
+                                      peer->supp_oper_classes_len);
+}
+
+
 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
                                   const u8 *buf, size_t len)
 {
@@ -1726,7 +1817,7 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
        lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
        if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
                wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
-               status = WLAN_STATUS_NOT_IN_SAME_BSS;
+               status = WLAN_STATUS_REQUEST_DECLINED;
                goto error;
        }
 
@@ -1945,18 +2036,8 @@ skip_rsn:
        wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
 
 skip_rsn_check:
-       /* add the peer to the driver as a "setup in progress" peer */
-       if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, peer->aid,
-                                   peer->capability,
-                                   peer->supp_rates, peer->supp_rates_len,
-                                   peer->ht_capabilities,
-                                   peer->vht_capabilities,
-                                   peer->qos_info, peer->ext_capab,
-                                   peer->ext_capab_len,
-                                   peer->supp_channels,
-                                   peer->supp_channels_len,
-                                   peer->supp_oper_classes,
-                                   peer->supp_oper_classes_len))
+       /* add supported rates, capabilities, and qos_info to the TDLS peer */
+       if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
                goto error;
 
        peer->tpk_in_progress = 1;
@@ -2256,17 +2337,7 @@ skip_rsn:
        peer->dtoken = dtoken;
 
        /* add supported rates, capabilities, and qos_info to the TDLS peer */
-       if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
-                                   peer->capability,
-                                   peer->supp_rates, peer->supp_rates_len,
-                                   peer->ht_capabilities,
-                                   peer->vht_capabilities,
-                                   peer->qos_info, peer->ext_capab,
-                                   peer->ext_capab_len,
-                                   peer->supp_channels,
-                                   peer->supp_channels_len,
-                                   peer->supp_oper_classes,
-                                   peer->supp_oper_classes_len) < 0)
+       if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
                goto error;
 
        wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
@@ -2435,17 +2506,7 @@ static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
 
 skip_rsn:
        /* add supported rates, capabilities, and qos_info to the TDLS peer */
-       if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
-                                   peer->capability,
-                                   peer->supp_rates, peer->supp_rates_len,
-                                   peer->ht_capabilities,
-                                   peer->vht_capabilities,
-                                   peer->qos_info, peer->ext_capab,
-                                   peer->ext_capab_len,
-                                   peer->supp_channels,
-                                   peer->supp_channels_len,
-                                   peer->supp_oper_classes,
-                                   peer->supp_oper_classes_len) < 0)
+       if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
                goto error;
 
        if (!peer->tpk_success) {
@@ -2457,14 +2518,12 @@ skip_rsn:
                ret = wpa_tdls_enable_link(sm, peer);
                if (ret < 0) {
                        wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
-                       wpa_tdls_do_teardown(
-                               sm, peer,
-                               WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+                       goto error;
                }
        }
        return ret;
 error:
-       wpa_tdls_disable_peer_link(sm, peer);
+       wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
        return -1;
 }