hostapd: Support 4-way handshake offload for AP/P2P GO
Add support for offloaded 4-way handshake in AP/P2P GO mode. For drivers supporting the AP PSK offload, wpa_supplicant/hostapd passes down the PSK for the driver to handle the 4-way handshake. The driver is expected to indicate port authorized event to indicate that the 4-way handshake is completed successfully. Signed-off-by: Vinayak Yadawad <vinayak.yadawad@broadcom.com>
This commit is contained in:
parent
77386f51ac
commit
da364180fb
9 changed files with 88 additions and 2 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include "common/ieee802_11_common.h"
|
#include "common/ieee802_11_common.h"
|
||||||
#include "common/hw_features_common.h"
|
#include "common/hw_features_common.h"
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
|
#include "crypto/sha1.h"
|
||||||
#include "wps/wps_defs.h"
|
#include "wps/wps_defs.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
#include "hostapd.h"
|
#include "hostapd.h"
|
||||||
|
@ -2026,6 +2027,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
||||||
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
|
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
|
|
||||||
|
/* If key management offload is enabled, configure PSK to the driver. */
|
||||||
|
if (wpa_key_mgmt_wpa_psk_no_sae(hapd->conf->wpa_key_mgmt) &&
|
||||||
|
(hapd->iface->drv_flags2 &
|
||||||
|
WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK)) {
|
||||||
|
if (hapd->conf->ssid.wpa_psk && hapd->conf->ssid.wpa_psk_set) {
|
||||||
|
os_memcpy(params->psk, hapd->conf->ssid.wpa_psk->psk,
|
||||||
|
PMK_LEN);
|
||||||
|
params->psk_len = PMK_LEN;
|
||||||
|
} else if (hapd->conf->ssid.wpa_passphrase &&
|
||||||
|
pbkdf2_sha1(hapd->conf->ssid.wpa_passphrase,
|
||||||
|
hapd->conf->ssid.ssid,
|
||||||
|
hapd->conf->ssid.ssid_len, 4096,
|
||||||
|
params->psk, PMK_LEN) == 0) {
|
||||||
|
params->psk_len = PMK_LEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params->head = (u8 *) head;
|
params->head = (u8 *) head;
|
||||||
params->head_len = head_len;
|
params->head_len = head_len;
|
||||||
params->tail = tail;
|
params->tail = tail;
|
||||||
|
|
|
@ -2186,6 +2186,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
union wpa_event_data *data)
|
union wpa_event_data *data)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = ctx;
|
struct hostapd_data *hapd = ctx;
|
||||||
|
struct sta_info *sta;
|
||||||
#ifndef CONFIG_NO_STDOUT_DEBUG
|
#ifndef CONFIG_NO_STDOUT_DEBUG
|
||||||
int level = MSG_DEBUG;
|
int level = MSG_DEBUG;
|
||||||
|
|
||||||
|
@ -2305,6 +2306,15 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
data->assoc_info.link_addr,
|
data->assoc_info.link_addr,
|
||||||
data->assoc_info.reassoc);
|
data->assoc_info.reassoc);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_PORT_AUTHORIZED:
|
||||||
|
/* Port authorized event for an associated STA */
|
||||||
|
sta = ap_get_sta(hapd, data->port_authorized.sta_addr);
|
||||||
|
if (sta)
|
||||||
|
ap_sta_set_authorized(hapd, sta, 1);
|
||||||
|
else
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"No STA info matching port authorized event found");
|
||||||
|
break;
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
case EVENT_UPDATE_DH:
|
case EVENT_UPDATE_DH:
|
||||||
if (!data)
|
if (!data)
|
||||||
|
|
|
@ -3573,8 +3573,12 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
sta->auth_alg != WLAN_AUTH_FILS_PK &&
|
sta->auth_alg != WLAN_AUTH_FILS_PK &&
|
||||||
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
|
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
|
||||||
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
|
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
|
||||||
} else
|
} else if (!(hapd->iface->drv_flags2 &
|
||||||
|
WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK)) {
|
||||||
|
/* The 4-way handshake offloaded case will have this handled
|
||||||
|
* based on the port authorized event. */
|
||||||
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
|
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
|
||||||
|
}
|
||||||
|
|
||||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) {
|
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) {
|
||||||
if (eloop_cancel_timeout(ap_handle_timer, hapd, sta) > 0) {
|
if (eloop_cancel_timeout(ap_handle_timer, hapd, sta) > 0) {
|
||||||
|
|
|
@ -1812,6 +1812,16 @@ struct wpa_driver_ap_params {
|
||||||
* mld_link_id - Link id for MLD BSS's
|
* mld_link_id - Link id for MLD BSS's
|
||||||
*/
|
*/
|
||||||
u8 mld_link_id;
|
u8 mld_link_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* psk - PSK passed to the driver for 4-way handshake offload
|
||||||
|
*/
|
||||||
|
u8 psk[PMK_LEN];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* psk_len - PSK length in bytes (0 = not set)
|
||||||
|
*/
|
||||||
|
size_t psk_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wpa_driver_mesh_bss_params {
|
struct wpa_driver_mesh_bss_params {
|
||||||
|
@ -2284,6 +2294,8 @@ struct wpa_driver_capa {
|
||||||
#define WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ 0x0000000000008000ULL
|
#define WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ 0x0000000000008000ULL
|
||||||
/** Driver supports SAE authentication offload in STA mode */
|
/** Driver supports SAE authentication offload in STA mode */
|
||||||
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA 0x0000000000010000ULL
|
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_STA 0x0000000000010000ULL
|
||||||
|
/** Driver support AP_PSK authentication offload */
|
||||||
|
#define WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK 0x0000000000020000ULL
|
||||||
u64 flags2;
|
u64 flags2;
|
||||||
|
|
||||||
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
||||||
|
@ -6672,10 +6684,19 @@ union wpa_event_data {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct port_authorized - Data for EVENT_PORT_AUTHORIZED
|
* struct port_authorized - Data for EVENT_PORT_AUTHORIZED
|
||||||
|
* @td_bitmap: For STA mode, transition disable bitmap, if received in
|
||||||
|
* EAPOL-Key msg 3/4
|
||||||
|
* @td_bitmap_len: For STA mode, length of td_bitmap
|
||||||
|
* @sta_addr: For AP mode, the MAC address of the associated STA
|
||||||
|
*
|
||||||
|
* This event is used to indicate that the port is authorized and
|
||||||
|
* open for normal data in STA and AP modes when 4-way handshake is
|
||||||
|
* offloaded to the driver.
|
||||||
*/
|
*/
|
||||||
struct port_authorized {
|
struct port_authorized {
|
||||||
const u8 *td_bitmap;
|
const u8 *td_bitmap;
|
||||||
size_t td_bitmap_len;
|
size_t td_bitmap_len;
|
||||||
|
const u8 *sta_addr;
|
||||||
} port_authorized;
|
} port_authorized;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5110,6 +5110,12 @@ static int wpa_driver_nl80211_set_ap(void *priv,
|
||||||
suites))
|
suites))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if ((params->key_mgmt_suites & WPA_KEY_MGMT_PSK) &&
|
||||||
|
(drv->capa.flags & WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK) &&
|
||||||
|
params->psk_len &&
|
||||||
|
nla_put(msg, NL80211_ATTR_PMK, params->psk_len, params->psk))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
|
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
|
||||||
(!params->pairwise_ciphers ||
|
(!params->pairwise_ciphers ||
|
||||||
params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
|
params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
|
||||||
|
|
|
@ -705,6 +705,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
|
||||||
if (ext_feature_isset(ext_features, len,
|
if (ext_feature_isset(ext_features, len,
|
||||||
NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
|
NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT))
|
||||||
capa->flags2 |= WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ;
|
capa->flags2 |= WPA_DRIVER_FLAGS2_SCAN_MIN_PREQ;
|
||||||
|
|
||||||
|
if (ext_feature_isset(ext_features, len,
|
||||||
|
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK))
|
||||||
|
capa->flags2 |= WPA_DRIVER_FLAGS2_4WAY_HANDSHAKE_AP_PSK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3506,7 +3506,13 @@ static void nl80211_port_authorized(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = nla_data(tb[NL80211_ATTR_MAC]);
|
addr = nla_data(tb[NL80211_ATTR_MAC]);
|
||||||
if (os_memcmp(addr, drv->bssid, ETH_ALEN) != 0) {
|
if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
|
||||||
|
event.port_authorized.sta_addr = addr;
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Port authorized for STA addr " MACSTR,
|
||||||
|
MAC2STR(addr));
|
||||||
|
} else if (is_sta_interface(drv->nlmode) &&
|
||||||
|
os_memcmp(addr, drv->bssid, ETH_ALEN) != 0) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Ignore port authorized event for " MACSTR
|
"nl80211: Ignore port authorized event for " MACSTR
|
||||||
" (not the currently connected BSSID " MACSTR ")",
|
" (not the currently connected BSSID " MACSTR ")",
|
||||||
|
|
|
@ -1058,6 +1058,7 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
|
||||||
return -1;
|
return -1;
|
||||||
hapd_iface->owner = wpa_s;
|
hapd_iface->owner = wpa_s;
|
||||||
hapd_iface->drv_flags = wpa_s->drv_flags;
|
hapd_iface->drv_flags = wpa_s->drv_flags;
|
||||||
|
hapd_iface->drv_flags2 = wpa_s->drv_flags2;
|
||||||
hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
|
hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads;
|
||||||
hapd_iface->extended_capa = wpa_s->extended_capa;
|
hapd_iface->extended_capa = wpa_s->extended_capa;
|
||||||
hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
|
hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "common/wpa_ctrl.h"
|
#include "common/wpa_ctrl.h"
|
||||||
#include "eap_peer/eap.h"
|
#include "eap_peer/eap.h"
|
||||||
#include "ap/hostapd.h"
|
#include "ap/hostapd.h"
|
||||||
|
#include "ap/sta_info.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
#include "fst/fst.h"
|
#include "fst/fst.h"
|
||||||
#include "wnm_sta.h"
|
#include "wnm_sta.h"
|
||||||
|
@ -6411,6 +6412,21 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
case EVENT_PORT_AUTHORIZED:
|
case EVENT_PORT_AUTHORIZED:
|
||||||
|
#ifdef CONFIG_AP
|
||||||
|
if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) {
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
sta = ap_get_sta(wpa_s->ap_iface->bss[0],
|
||||||
|
data->port_authorized.sta_addr);
|
||||||
|
if (sta)
|
||||||
|
ap_sta_set_authorized(wpa_s->ap_iface->bss[0],
|
||||||
|
sta, 1);
|
||||||
|
else
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"No STA info matching port authorized event found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_AP */
|
||||||
#ifndef CONFIG_NO_WPA
|
#ifndef CONFIG_NO_WPA
|
||||||
if (data->port_authorized.td_bitmap_len) {
|
if (data->port_authorized.td_bitmap_len) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
|
Loading…
Reference in a new issue