diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 8f776cf7e..656b820eb 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -31,6 +31,7 @@ #include "wps_hostapd.h" #include "ap_drv_ops.h" #include "ap_config.h" +#include "ap_mlme.h" #include "hw_features.h" #include "dfs.h" #include "beacon.h" @@ -381,6 +382,39 @@ skip_wpa_check: sta->auth_alg, req_ies, req_ies_len); #endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_FILS + if (sta->auth_alg == WLAN_AUTH_FILS_SK || + sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || + sta->auth_alg == WLAN_AUTH_FILS_PK) { + if (!wpa_fils_validate_fils_session(sta->wpa_sm, req_ies, + req_ies_len, + sta->fils_session)) { + wpa_printf(MSG_DEBUG, + "FILS: Session validation failed"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + res = wpa_fils_validate_key_confirm(sta->wpa_sm, req_ies, + req_ies_len); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "FILS: Key Confirm validation failed"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (!elems.fils_session) { + wpa_printf(MSG_DEBUG, + "FILS: Session element not found"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + p = hostapd_eid_assoc_fils_session(sta->wpa_sm, p, + elems.fils_session); + wpa_hexdump(MSG_DEBUG, "FILS Assoc Resp BUF (IEs)", + buf, p - buf); + } +#endif /* CONFIG_FILS */ + #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); @@ -723,6 +757,32 @@ static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst, #endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_FILS +static void hostapd_notify_auth_fils_finish(struct hostapd_data *hapd, + struct sta_info *sta, u16 resp, + struct wpabuf *data, int pub) +{ + if (resp == WLAN_STATUS_SUCCESS) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "authentication OK (FILS)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->auth_alg = WLAN_AUTH_FILS_SK; + mlme_authenticate_indication(hapd, sta); + } else { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication failed (FILS)"); + } + + hostapd_sta_auth(hapd, sta->addr, 2, resp, + data ? wpabuf_head(data) : NULL, + data ? wpabuf_len(data) : 0); + wpabuf_free(data); +} +#endif /* CONFIG_FILS */ + + static void hostapd_notif_auth(struct hostapd_data *hapd, struct auth_info *rx_auth) { @@ -760,6 +820,18 @@ static void hostapd_notif_auth(struct hostapd_data *hapd, return; } #endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FILS + if (rx_auth->auth_type == WLAN_AUTH_FILS_SK) { + sta->auth_alg = WLAN_AUTH_FILS_SK; + handle_auth_fils(hapd, sta, rx_auth->ies, rx_auth->ies_len, + rx_auth->auth_type, rx_auth->auth_transaction, + rx_auth->status_code, + hostapd_notify_auth_fils_finish); + return; + } +#endif /* CONFIG_FILS */ + fail: hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1, status, resp_ies, resp_ies_len); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index fcd4736c9..172f20ffa 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2509,6 +2509,36 @@ int fils_set_tk(struct wpa_state_machine *sm) return 0; } + +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, + const u8 *fils_session) +{ + struct wpabuf *plain; + u8 *pos = buf; + + /* FILS Session */ + *pos++ = WLAN_EID_EXTENSION; /* Element ID */ + *pos++ = 1 + FILS_SESSION_LEN; /* Length */ + *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */ + os_memcpy(pos, fils_session, FILS_SESSION_LEN); + pos += FILS_SESSION_LEN; + + plain = fils_prepare_plainbuf(sm, NULL); + if (!plain) { + wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); + return NULL; + } + + os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); + pos += wpabuf_len(plain); + + wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, + (unsigned int) wpabuf_len(plain)); + wpabuf_free(plain); + sm->fils_completed = 1; + return pos; +} + #endif /* CONFIG_FILS */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 384fa6c08..2e3b78253 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -374,6 +374,8 @@ int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, size_t current_len, size_t max_len, const struct wpabuf *hlp); int fils_set_tk(struct wpa_state_machine *sm); +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid, + const u8 *fils_session); const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len, const u8 *fils_session);