- Add basic ML IE in SAE auth frames - Use TA address provided by driver for sending SAE auth frames - Use MLD address for SAE PWE derivation - Allow auth frames with RA address same as TA address provided by driver Signed-off-by: Veerendranath Jakkam <quic_vjakkam@xxxxxxxxxxx> --- src/drivers/driver.h | 3 + src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_event.c | 20 ++++++- wpa_supplicant/sme.c | 96 ++++++++++++++++++++++-------- wpa_supplicant/wpa_supplicant_i.h | 2 + 5 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 9a2d9bbc2..02c6604ce 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2595,6 +2595,8 @@ enum wpa_drv_update_connect_params_mask { * the real status code for failures. Used only for the request interface * from user space to the driver. * @pmkid: Generated PMKID as part of external auth exchange (e.g., SAE). + * @tx_addr: Transmit address to be used for the authentication frames. Optional + * for the request interface. */ struct external_auth { enum { @@ -2607,6 +2609,7 @@ struct external_auth { unsigned int key_mgmt_suite; u16 status; const u8 *pmkid; + const u8 *tx_addr; }; /* enum nested_attr - Used to specify if subcommand uses nested attributes */ diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 44ac7ea95..773045ca4 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -80,6 +80,7 @@ struct i802_bss { struct nl80211_wiphy_data *wiphy_data; struct dl_list wiphy_list; u8 rand_addr[ETH_ALEN]; + u8 ext_auth_rand_addr[ETH_ALEN]; }; struct drv_nl80211_if_info { diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index f756eaa1b..abe944876 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1206,15 +1206,22 @@ static void mlme_event(struct i802_bss *bss, nl80211_command_to_string(cmd), bss->ifname, MAC2STR(bss->addr), MAC2STR(data + 4), MAC2STR(data + 4 + ETH_ALEN)); + + if (!is_zero_ether_addr(bss->ext_auth_rand_addr) && + os_memcmp(bss->ext_auth_rand_addr, data + 4, ETH_ALEN) == 0) + goto skip_ra_check; + if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) && os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 && (is_zero_ether_addr(bss->rand_addr) || os_memcmp(bss->rand_addr, data + 4, ETH_ALEN) != 0) && os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) { - wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event " + wpa_printf(MSG_MSGDUMP, "nl80211: %s: skip check for Ignore MLME frame event " "for foreign address", bss->ifname); return; } + +skip_ra_check: wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame", nla_data(frame), nla_len(frame)); @@ -2798,6 +2805,17 @@ static void nl80211_external_auth(struct wpa_driver_nl80211_data *drv, event.external_auth.bssid = nla_data(tb[NL80211_ATTR_BSSID]); + if (tb[NL80211_ATTR_MAC]) { + event.external_auth.tx_addr = nla_data(tb[NL80211_ATTR_MAC]); + wpa_printf(MSG_ERROR, "TA addr for external auth: " MACSTR, + MAC2STR(event.external_auth.tx_addr)); + os_memcpy(drv->first_bss->ext_auth_rand_addr, + event.external_auth.tx_addr, + ETH_ALEN); + } else { + os_memset(drv->first_bss->ext_auth_rand_addr, 0, ETH_ALEN); + } + wpa_printf(MSG_DEBUG, "nl80211: External auth action: %u, AKM: 0x%x", event.external_auth.action, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 2dad36ddc..d5f5d1f0d 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -95,7 +95,9 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, int use_pt = 0; bool use_pk = false; u8 rsnxe_capa = 0; + const u8 *peer_addr = bssid; + wpa_s->sme.ext_ml_auth = false; if (ret_use_pt) *ret_use_pt = 0; if (ret_use_pk) @@ -124,19 +126,6 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, return NULL; } - if (reuse && wpa_s->sme.sae.tmp && - os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, - "SAE: Reuse previously generated PWE on a retry with the same AP"); - use_pt = wpa_s->sme.sae.h2e; - use_pk = wpa_s->sme.sae.pk; - goto reuse_data; - } - if (sme_set_sae_group(wpa_s) < 0) { - wpa_printf(MSG_DEBUG, "SAE: Failed to select group"); - return NULL; - } - bss = wpa_bss_get_bssid_latest(wpa_s, bssid); if (!bss) { wpa_printf(MSG_DEBUG, @@ -150,6 +139,27 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); if (rsnxe && rsnxe[1] >= 1) rsnxe_capa = rsnxe[2]; + + if (external && !is_zero_ether_addr(bss->mld_addr)) { + wpa_printf(MSG_DEBUG, "SAE: AP MLD Addr: " MACSTR, + MAC2STR(bss->mld_addr)); + + wpa_s->sme.ext_ml_auth = true; + peer_addr = bss->mld_addr; + } + } + + if (reuse && wpa_s->sme.sae.tmp && + os_memcmp(peer_addr, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, + "SAE: Reuse previously generated PWE on a retry with the same AP"); + use_pt = wpa_s->sme.sae.h2e; + use_pk = wpa_s->sme.sae.pk; + goto reuse_data; + } + if (sme_set_sae_group(wpa_s) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Failed to select group"); + return NULL; } if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3) @@ -190,24 +200,24 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, if (use_pt && sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt, - wpa_s->own_addr, bssid, + wpa_s->own_addr, peer_addr, wpa_s->sme.sae_rejected_groups, NULL) < 0) return NULL; if (!use_pt && - sae_prepare_commit(wpa_s->own_addr, bssid, + sae_prepare_commit(wpa_s->own_addr, peer_addr, (u8 *) password, os_strlen(password), &wpa_s->sme.sae) < 0) { wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); return NULL; } if (wpa_s->sme.sae.tmp) { - os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN); + os_memcpy(wpa_s->sme.sae.tmp->bssid, peer_addr, ETH_ALEN); if (use_pt && use_pk) wpa_s->sme.sae.pk = 1; #ifdef CONFIG_SAE_PK os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr, ETH_ALEN); - os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN); + os_memcpy(wpa_s->sme.sae.tmp->peer_addr, peer_addr, ETH_ALEN); sae_pk_set_password(&wpa_s->sme.sae, password); #endif /* CONFIG_SAE_PK */ } @@ -1041,11 +1051,26 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, #ifdef CONFIG_SAE +#define WPA_AUTH_FRAME_ML_IE_LEN (6+ETH_ALEN) + +static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr) +{ + + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + wpabuf_put_u8(buf, WPA_AUTH_FRAME_ML_IE_LEN -2); + wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK); + wpabuf_put_u8(buf, 0x0); + wpabuf_put_u8(buf, 0x0); + wpabuf_put_u8(buf, 0x7); + wpabuf_put_data(buf, mld_addr, ETH_ALEN); +} + + static int sme_external_auth_build_buf(struct wpabuf *buf, struct wpabuf *params, const u8 *sa, const u8 *da, u16 auth_transaction, u16 seq_num, - u16 status_code) + u16 status_code, const u8 *mld_addr) { struct ieee80211_mgmt *resp; @@ -1064,10 +1089,17 @@ static int sme_external_auth_build_buf(struct wpabuf *buf, if (params) wpabuf_put_buf(buf, params); + if(mld_addr) { + wpa_auth_ml_ie(buf, mld_addr); + wpa_hexdump(MSG_DEBUG, "ML Auth Frame", wpabuf_head(buf), + wpabuf_len(buf)); + } + return 0; } + static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, const u8 *bssid, struct wpa_ssid *ssid) @@ -1085,7 +1117,9 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, } wpa_s->sme.sae.state = SAE_COMMITTED; - buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp)); + buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) + + (wpa_s->sme.ext_ml_auth ? + WPA_AUTH_FRAME_ML_IE_LEN : 0)); if (!buf) { wpabuf_free(resp); return -1; @@ -1098,8 +1132,10 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; else status = WLAN_STATUS_SUCCESS; - sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, - bssid, 1, wpa_s->sme.seq_num, status); + sme_external_auth_build_buf(buf, resp, wpa_s->sme.ext_auth_tx_addr, + bssid, 1, wpa_s->sme.seq_num, status, + wpa_s->sme.ext_ml_auth ? + wpa_s->own_addr : NULL); wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); @@ -1160,16 +1196,20 @@ static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s, } wpa_s->sme.sae.state = SAE_CONFIRMED; - buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp)); + buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) + + (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN : 0)); if (!buf) { wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure"); wpabuf_free(resp); return; } wpa_s->sme.seq_num++; - sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, + sme_external_auth_build_buf(buf, resp, wpa_s->sme.ext_auth_tx_addr, da, 2, wpa_s->sme.seq_num, - WLAN_STATUS_SUCCESS); + WLAN_STATUS_SUCCESS, + wpa_s->sme.ext_ml_auth ? + wpa_s->own_addr : NULL); + wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); @@ -1183,11 +1223,19 @@ void sme_external_auth_trigger(struct wpa_supplicant *wpa_s, RSN_AUTH_KEY_MGMT_SAE) return; + if (!data->external_auth.tx_addr) + data->external_auth.tx_addr = wpa_s->own_addr; + + wpa_printf(MSG_DEBUG, "SAE: External auth transmit address " MACSTR, + MAC2STR(data->external_auth.tx_addr)); + if (data->external_auth.action == EXT_AUTH_START) { if (!data->external_auth.bssid || !data->external_auth.ssid) return; os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid, ETH_ALEN); + os_memcpy(wpa_s->sme.ext_auth_tx_addr, data->external_auth.tx_addr, + ETH_ALEN); os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid, data->external_auth.ssid_len); wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0ee4c01f9..e881ce1b5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1024,6 +1024,8 @@ struct wpa_supplicant { u8 ext_auth_bssid[ETH_ALEN]; u8 ext_auth_ssid[SSID_MAX_LEN]; size_t ext_auth_ssid_len; + u8 ext_auth_tx_addr[ETH_ALEN]; + bool ext_ml_auth; int *sae_rejected_groups; #endif /* CONFIG_SAE */ } sme; -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap