[PATCH v4 11/13] MLD STA: Add support for SAE external authentication
Veerendranath Jakkam
quic_vjakkam at quicinc.com
Thu Nov 3 01:08:54 PDT 2022
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 at quicinc.com>
---
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 2e199c49a..1777236e7 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1425,6 +1425,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.
*/
@@ -1453,6 +1457,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));
@@ -3131,6 +3137,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
More information about the Hostap
mailing list