This commit does below: - Enable MLO for SAE authentication when driver indicates transmit address(TA). - Add basic ML IE in SAE authentication frames. - Use TA address provided by driver for sending SAE authentication frames. - Use MLD address for SAE PWE derivation. - Allow authentication 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 | 17 +++++ wpa_supplicant/sme.c | 107 ++++++++++++++++++++++------- wpa_supplicant/wpa_supplicant_i.h | 2 + 5 files changed, 106 insertions(+), 24 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 573dd7dd5..0fe416928 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2623,6 +2623,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 { @@ -2635,6 +2637,7 @@ struct external_auth { unsigned int key_mgmt_suite; u16 status; const u8 *pmkid; + const u8 *tx_addr; }; #define WPAS_MAX_PASN_PEERS 10 diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 0b8b0ce11..40e845d78 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 289a9c734..beab202ff 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1288,6 +1288,10 @@ static void mlme_event(struct i802_bss *bss, 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; + /* PASN Authentication frame can be received with a different source MAC * address. Allow NL80211_CMD_FRAME event with foreign addresses also. */ @@ -1316,6 +1320,8 @@ static void mlme_event(struct i802_bss *bss, "for foreign address", bss->ifname); return; } + +skip_ra_check: wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame", nla_data(frame), nla_len(frame)); @@ -2994,6 +3000,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 896fa9df4..e6e39c4c3 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -95,6 +95,7 @@ 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; if (ret_use_pt) *ret_use_pt = 0; @@ -124,19 +125,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 +138,31 @@ 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 && wpa_s->sme.ext_ml_auth) { + if (is_zero_ether_addr(bss->mld_addr)) { + wpa_printf(MSG_DEBUG, + "SAE: BSS not affliated with MLD"); + return NULL; + } + + wpa_printf(MSG_DEBUG, "SAE: AP MLD address: " MACSTR, + MAC2STR(bss->mld_addr)); + 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 +203,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 +1054,30 @@ 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); + + /* Basic Multi-Link IE control field */ + wpabuf_put_u8(buf, 0x0); + wpabuf_put_u8(buf, 0x0); + + /* Common info: Common Info Length + MLD MAC LEN */ + 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 +1096,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 +1124,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 +1139,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); @@ -1166,16 +1209,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); @@ -1206,11 +1253,23 @@ void sme_external_auth_trigger(struct wpa_supplicant *wpa_s, if (!is_sae_key_mgmt_suite(data->external_auth.key_mgmt_suite)) return; + if (data->external_auth.tx_addr) { + wpa_s->sme.ext_ml_auth = true; + wpa_printf(MSG_DEBUG, + "SAE: External multi-link authentication with transmit address " MACSTR, + MAC2STR(data->external_auth.tx_addr)); + } else { + data->external_auth.tx_addr = wpa_s->own_addr; + wpa_s->sme.ext_ml_auth = false; + } + 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 9db847cec..68ca5229f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1034,6 +1034,8 @@ struct wpa_supplicant { struct wpa_ssid *ext_auth_wpa_ssid; 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