hostapd: Add support for SAE offload for AP interface
The driver advertising SAE AP offload support would take care of SAE authentication and PMK generation at the driver/firmware. This feature requires the driver to be supporting 4-way handshake offload to process the generated PMK at the driver level for 4-way handshake. Signed-off-by: Vinayak Yadawad <vinayak.yadawad@broadcom.com>
This commit is contained in:
parent
d984c7b298
commit
b089803091
9 changed files with 95 additions and 13 deletions
|
@ -2044,6 +2044,33 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
/* If SAE offload is enabled, provide password to lower layer for
|
||||
* SAE authentication and PMK generation.
|
||||
*/
|
||||
if (wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
||||
(hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP)) {
|
||||
if (hostapd_sae_pk_in_use(hapd->conf)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"SAE PK not supported with SAE offload");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hostapd_sae_pw_id_in_use(hapd->conf)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"SAE Password Identifiers not supported with SAE offload");
|
||||
return -1;
|
||||
}
|
||||
|
||||
params->sae_password = sae_get_password(hapd, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (!params->sae_password) {
|
||||
wpa_printf(MSG_ERROR, "SAE password not configured for offload");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
params->head = (u8 *) head;
|
||||
params->head_len = head_len;
|
||||
params->tail = tail;
|
||||
|
|
|
@ -540,12 +540,12 @@ static void sae_set_state(struct sta_info *sta, enum sae_state state,
|
|||
}
|
||||
|
||||
|
||||
static const char * sae_get_password(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const char *rx_id,
|
||||
struct sae_password_entry **pw_entry,
|
||||
struct sae_pt **s_pt,
|
||||
const struct sae_pk **s_pk)
|
||||
const char * sae_get_password(struct hostapd_data *hapd,
|
||||
struct sta_info *sta,
|
||||
const char *rx_id,
|
||||
struct sae_password_entry **pw_entry,
|
||||
struct sae_pt **s_pt,
|
||||
const struct sae_pk **s_pk)
|
||||
{
|
||||
const char *password = NULL;
|
||||
struct sae_password_entry *pw;
|
||||
|
@ -555,7 +555,8 @@ static const char * sae_get_password(struct hostapd_data *hapd,
|
|||
|
||||
for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
|
||||
if (!is_broadcast_ether_addr(pw->peer_addr) &&
|
||||
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
|
||||
(!sta ||
|
||||
os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0))
|
||||
continue;
|
||||
if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
|
||||
continue;
|
||||
|
@ -573,7 +574,7 @@ static const char * sae_get_password(struct hostapd_data *hapd,
|
|||
pt = hapd->conf->ssid.pt;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
if (!password && sta) {
|
||||
for (psk = sta->psk; psk; psk = psk->next) {
|
||||
if (psk->is_passphrase) {
|
||||
password = psk->passphrase;
|
||||
|
|
|
@ -20,6 +20,9 @@ struct radius_sta;
|
|||
enum ieee80211_op_mode;
|
||||
enum oper_chan_width;
|
||||
struct ieee802_11_elems;
|
||||
struct sae_pk;
|
||||
struct sae_pt;
|
||||
struct sae_password_entry;
|
||||
|
||||
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
|
||||
struct hostapd_frame_info *fi);
|
||||
|
@ -238,5 +241,9 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
|
|||
void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
|
||||
enum oper_chan_width *width, u8 *seg0, u8 *seg1);
|
||||
bool hostapd_is_mld_ap(struct hostapd_data *hapd);
|
||||
const char * sae_get_password(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, const char *rx_id,
|
||||
struct sae_password_entry **pw_entry,
|
||||
struct sae_pt **s_pt, const struct sae_pk **s_pk);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
|
|
@ -395,6 +395,7 @@ struct wpa_auth_callbacks {
|
|||
int (*get_ml_rsn_info)(void *ctx, struct wpa_auth_ml_rsn_info *info);
|
||||
int (*get_ml_key_info)(void *ctx, struct wpa_auth_ml_key_info *info);
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
int (*get_drv_flags)(void *ctx, u64 *drv_flags, u64 *drv_flags2);
|
||||
};
|
||||
|
||||
struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||
|
|
|
@ -1601,6 +1601,20 @@ static int hostapd_wpa_auth_get_ml_key_info(void *ctx,
|
|||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
|
||||
static int hostapd_wpa_auth_get_drv_flags(void *ctx,
|
||||
u64 *drv_flags, u64 *drv_flags2)
|
||||
{
|
||||
struct hostapd_data *hapd = ctx;
|
||||
|
||||
if (drv_flags)
|
||||
*drv_flags = hapd->iface->drv_flags;
|
||||
if (drv_flags2)
|
||||
*drv_flags2 = hapd->iface->drv_flags2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_setup_wpa(struct hostapd_data *hapd)
|
||||
{
|
||||
struct wpa_auth_config _conf;
|
||||
|
@ -1655,6 +1669,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|||
.get_ml_rsn_info = hostapd_wpa_auth_get_ml_rsn_info,
|
||||
.get_ml_key_info = hostapd_wpa_auth_get_ml_key_info,
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
.get_drv_flags = hostapd_wpa_auth_get_drv_flags,
|
||||
};
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "drivers/driver.h"
|
||||
#include "eapol_auth/eapol_auth_sm.h"
|
||||
#include "ap_config.h"
|
||||
#include "ieee802_11.h"
|
||||
|
@ -1013,11 +1014,23 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE && data.num_pmkid &&
|
||||
!sm->pmksa) {
|
||||
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"No PMKSA cache entry found for SAE");
|
||||
return WPA_INVALID_PMKID;
|
||||
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE) {
|
||||
u64 drv_flags = 0;
|
||||
u64 drv_flags2 = 0;
|
||||
bool ap_sae_offload = false;
|
||||
|
||||
if (wpa_auth->cb->get_drv_flags &&
|
||||
wpa_auth->cb->get_drv_flags(wpa_auth->cb_ctx, &drv_flags,
|
||||
&drv_flags2) == 0)
|
||||
ap_sae_offload =
|
||||
!!(drv_flags2 &
|
||||
WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP);
|
||||
|
||||
if (!ap_sae_offload && data.num_pmkid && !sm->pmksa) {
|
||||
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||
"No PMKSA cache entry found for SAE");
|
||||
return WPA_INVALID_PMKID;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
|
|
|
@ -1822,6 +1822,11 @@ struct wpa_driver_ap_params {
|
|||
* psk_len - PSK length in bytes (0 = not set)
|
||||
*/
|
||||
size_t psk_len;
|
||||
|
||||
/**
|
||||
* sae_password - SAE password for SAE offload
|
||||
*/
|
||||
const char *sae_password;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_bss_params {
|
||||
|
@ -2300,6 +2305,8 @@ struct wpa_driver_capa {
|
|||
#define WPA_DRIVER_FLAGS2_OWE_OFFLOAD_STA 0x0000000000040000ULL
|
||||
/** Driver supports OWE AP offload */
|
||||
#define WPA_DRIVER_FLAGS2_OWE_OFFLOAD_AP 0x0000000000080000ULL
|
||||
/** Driver support AP SAE authentication offload */
|
||||
#define WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP 0x0000000000100000ULL
|
||||
u64 flags2;
|
||||
|
||||
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
||||
|
|
|
@ -5116,6 +5116,13 @@ static int wpa_driver_nl80211_set_ap(void *priv,
|
|||
nla_put(msg, NL80211_ATTR_PMK, params->psk_len, params->psk))
|
||||
goto fail;
|
||||
|
||||
if (wpa_key_mgmt_sae(params->key_mgmt_suites) &&
|
||||
(drv->capa.flags2 & WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP) &&
|
||||
params->sae_password &&
|
||||
nla_put(msg, NL80211_ATTR_SAE_PASSWORD,
|
||||
os_strlen(params->sae_password), params->sae_password))
|
||||
goto fail;
|
||||
|
||||
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
|
||||
(!params->pairwise_ciphers ||
|
||||
params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
|
||||
|
|
|
@ -717,6 +717,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
|
|||
if (ext_feature_isset(ext_features, len,
|
||||
NL80211_EXT_FEATURE_OWE_OFFLOAD_AP))
|
||||
capa->flags2 |= WPA_DRIVER_FLAGS2_OWE_OFFLOAD_AP;
|
||||
|
||||
if (ext_feature_isset(ext_features, len,
|
||||
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP))
|
||||
capa->flags2 |= WPA_DRIVER_FLAGS2_SAE_OFFLOAD_AP;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue