From 75fa7d19a4893df18a77427f43789b2922cf353e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 3 Apr 2013 18:39:10 +0300 Subject: [PATCH] TDLS: Fix key configuration with current mac80211 A kernel commit ("mac80211: fix FT roaming") started validating that the STA entry is marked associated when adding a key. While this is needed to fix some FT use cases with hardware crypto, it has a side effect of breaking TDLS key configuration. Work around this by trying to re-configure the key for the direct link after the STA entry has been set with all information. In addition, try to tear down the link if anything goes wrong in key configuration (if both attempts fail) or enabling the link in the driver. Signed-hostap: Jouni Malinen --- src/rsn_supp/tdls.c | 68 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 8ceaf6c3e..069e22bee 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -86,6 +86,7 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer); struct wpa_tdls_peer { struct wpa_tdls_peer *next; + unsigned int reconfig_key:1; int initiator; /* whether this end was initiator for TDLS setup */ u8 addr[ETH_ALEN]; /* other end MAC address */ u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ @@ -616,6 +617,7 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) MAC2STR(peer->addr)); eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); + peer->reconfig_key = 0; peer->initiator = 0; os_free(peer->sm_tmr.buf); peer->sm_tmr.buf = NULL; @@ -1751,7 +1753,7 @@ error: } -static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) +static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) { peer->tpk_success = 1; eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); @@ -1775,13 +1777,22 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) } /* add supported rates, capabilities, and qos_info to the TDLS peer */ - wpa_sm_tdls_peer_addset(sm, peer->addr, 0, 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); + if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, 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) < 0) + return -1; - wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); + if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) { + wpa_printf(MSG_INFO, "TDLS: Could not configure key to the " + "driver"); + return -1; + } + peer->reconfig_key = 0; + + return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); } @@ -1800,6 +1811,7 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, int ielen; u16 status; const u8 *pos; + int ret; wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 " "(Peer " MACSTR ")", MAC2STR(src_addr)); @@ -1992,7 +2004,15 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, return -1; } - wpa_tdls_set_key(sm, peer); + if (wpa_tdls_set_key(sm, peer) < 0) { + /* + * Some drivers may not be able to config the key prior to full + * STA entry having been configured. + */ + wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " + "STA entry is complete"); + peer->reconfig_key = 1; + } skip_rsn: peer->dtoken = dtoken; @@ -2001,9 +2021,13 @@ skip_rsn: "TPK Handshake Message 3"); wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer); - wpa_tdls_enable_link(sm, peer); - - return 0; + 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, 1); + } + return ret; error: wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, @@ -2026,6 +2050,7 @@ static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, u16 status; const u8 *pos; u32 lifetime; + int ret; wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 " "(Peer " MACSTR ")", MAC2STR(src_addr)); @@ -2136,13 +2161,24 @@ static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, return -1; } - if (wpa_tdls_set_key(sm, peer) < 0) - return -1; + if (wpa_tdls_set_key(sm, peer) < 0) { + /* + * Some drivers may not be able to config the key prior to full + * STA entry having been configured. + */ + wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after " + "STA entry is complete"); + peer->reconfig_key = 1; + } skip_rsn: - wpa_tdls_enable_link(sm, peer); - - return 0; + 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, 1); + } + return ret; }