From a206e2a1755cefa3ec041d00dd97cc88f05b87f1 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 7 Jan 2015 01:10:56 -0500 Subject: [PATCH] SAE: Centralize function for sending initial COMMIT When performing SAE authentication in mesh, one station may initiate authentication by sending a COMMIT as soon as a peer candidate is discovered. Previously we did this in mesh_rsn.c, but this left some of the state initialization in a different part of the code from the rest of the state machine, and we may need to add other initializations here in the future, so move that to a more central function. Signed-off-by: Bob Copeland --- src/ap/ieee802_11.c | 31 ++++++++++++++ src/ap/ieee802_11.h | 2 + wpa_supplicant/mesh_rsn.c | 89 +++++++-------------------------------- 3 files changed, 48 insertions(+), 74 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 97f98f28e..0459a1787 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -755,6 +755,37 @@ reply: } wpabuf_free(data); } + + +/** + * auth_sae_init_committed - Send COMMIT and start SAE in committed state + * @hapd: BSS data for the device initiating the authentication + * @sta: the peer to which commit authentication frame is sent + * + * This function implements Init event handling (IEEE Std 802.11-2012, + * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the + * sta->sae structure should be initialized appropriately via a call to + * sae_prepare_commit(). + */ +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta) +{ + int ret; + + if (!sta->sae || !sta->sae->tmp) + return -1; + + if (sta->sae->state != SAE_NOTHING) + return -1; + + ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); + if (ret) + return -1; + + sta->sae->state = SAE_COMMITTED; + + return 0; +} + #endif /* CONFIG_SAE */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index cf0d3f2bf..8229c5e50 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -89,4 +89,6 @@ int hostapd_update_time_adv(struct hostapd_data *hapd); void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); + #endif /* IEEE802_11_H */ diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index e6ae7c38b..aee325a3e 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -18,6 +18,7 @@ #include "ap/hostapd.h" #include "ap/wpa_auth.h" #include "ap/sta_info.h" +#include "ap/ieee802_11.h" #include "wpa_supplicant_i.h" #include "driver_i.h" #include "wpas_glue.h" @@ -245,80 +246,23 @@ static int mesh_rsn_sae_group(struct wpa_supplicant *wpa_s, } -struct wpabuf * -mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid, struct sta_info *sta) +static int mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + struct sta_info *sta) { - struct wpabuf *buf; - int len; - if (ssid->passphrase == NULL) { wpa_msg(wpa_s, MSG_DEBUG, "SAE: No password available"); - return NULL; + return -1; } if (mesh_rsn_sae_group(wpa_s, sta->sae) < 0) { wpa_msg(wpa_s, MSG_DEBUG, "SAE: Failed to select group"); - return NULL; + return -1; } - if (sae_prepare_commit(wpa_s->own_addr, sta->addr, - (u8 *) ssid->passphrase, - os_strlen(ssid->passphrase), sta->sae) < 0) { - wpa_msg(wpa_s, MSG_DEBUG, "SAE: Could not pick PWE"); - return NULL; - } - - len = wpa_s->mesh_rsn->sae_token ? - wpabuf_len(wpa_s->mesh_rsn->sae_token) : 0; - buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len); - if (buf == NULL) - return NULL; - - sae_write_commit(sta->sae, buf, wpa_s->mesh_rsn->sae_token); - - return buf; -} - - -static void mesh_rsn_send_auth(struct wpa_supplicant *wpa_s, - const u8 *dst, const u8 *src, - u16 auth_transaction, u16 resp, - struct wpabuf *data) -{ - struct ieee80211_mgmt *auth; - u8 *buf; - size_t len, ielen = 0; - - if (data) - ielen = wpabuf_len(data); - len = IEEE80211_HDRLEN + sizeof(auth->u.auth) + ielen; - buf = os_zalloc(len); - if (buf == NULL) - return; - - auth = (struct ieee80211_mgmt *) buf; - auth->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - os_memcpy(auth->da, dst, ETH_ALEN); - os_memcpy(auth->sa, src, ETH_ALEN); - os_memcpy(auth->bssid, src, ETH_ALEN); - - auth->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE); - auth->u.auth.auth_transaction = host_to_le16(auth_transaction); - auth->u.auth.status_code = host_to_le16(resp); - - if (data) - os_memcpy(auth->u.auth.variable, wpabuf_head(data), ielen); - - wpa_msg(wpa_s, MSG_DEBUG, "authentication frame: STA=" MACSTR - " auth_transaction=%d resp=%d (IE len=%lu)", - MAC2STR(dst), auth_transaction, resp, (unsigned long) ielen); - if (wpa_drv_send_mlme(wpa_s, buf, len, 0) < 0) - wpa_printf(MSG_INFO, "send_auth_reply: send_mlme failed: %s", - strerror(errno)); - - os_free(buf); + return sae_prepare_commit(wpa_s->own_addr, sta->addr, + (u8 *) ssid->passphrase, + os_strlen(ssid->passphrase), sta->sae); } @@ -326,9 +270,10 @@ static void mesh_rsn_send_auth(struct wpa_supplicant *wpa_s, int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, struct sta_info *sta) { + struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; struct wpa_ssid *ssid = wpa_s->current_ssid; - struct wpabuf *buf; unsigned int rnd; + int ret; if (!ssid) { wpa_msg(wpa_s, MSG_DEBUG, @@ -342,25 +287,21 @@ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, return -1; } - buf = mesh_rsn_build_sae_commit(wpa_s, ssid, sta); - if (!buf) + if (mesh_rsn_build_sae_commit(wpa_s, ssid, sta)) return -1; wpa_msg(wpa_s, MSG_DEBUG, "AUTH: started authentication with SAE peer: " MACSTR, MAC2STR(sta->addr)); - sta->sae->state = SAE_COMMITTED; wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); - - mesh_rsn_send_auth(wpa_s, sta->addr, wpa_s->own_addr, - 1, WLAN_STATUS_SUCCESS, buf); + ret = auth_sae_init_committed(hapd, sta); + if (ret) + return ret; rnd = rand() % MESH_AUTH_TIMEOUT; eloop_register_timeout(MESH_AUTH_TIMEOUT + rnd, 0, mesh_auth_timer, wpa_s, sta); - wpabuf_free(buf); - return 0; }