[PATCH v2 14/15] wpa_supplicant: Support parsing ML element in SAE auth frames

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Nov 30 05:09:38 PST 2022


Skip SAE fixed auth body fields, so the parsing is done at correct
offset.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/ap/ieee802_11.c              |  3 ++-
 src/common/common_module_tests.c |  2 +-
 src/common/sae.c                 |  5 ++++-
 src/common/sae.h                 |  2 +-
 src/pasn/pasn_initiator.c        |  2 +-
 src/pasn/pasn_responder.c        |  2 +-
 tests/fuzzing/sae/sae.c          |  4 ++--
 wpa_supplicant/sme.c             | 32 +++++++++++++++++++++++---------
 8 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index ba3c6009e4..6b0dc0690b 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1348,7 +1348,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 					mgmt->u.auth.variable, &token,
 					&token_len, groups, status_code ==
 					WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
-					status_code == WLAN_STATUS_SAE_PK);
+					status_code == WLAN_STATUS_SAE_PK,
+					NULL);
 		if (resp == SAE_SILENTLY_DISCARD) {
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Drop commit message from " MACSTR " due to reflection attack",
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 8aba713f92..a95ae36dc0 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -428,7 +428,7 @@ static int sae_tests(void)
 	}
 
 	if (sae_parse_commit(&sae, peer_commit, sizeof(peer_commit), NULL, NULL,
-			     NULL, 0) != 0 ||
+			     NULL, 0, NULL) != 0 ||
 	    sae_process_commit(&sae) < 0)
 		goto fail;
 
diff --git a/src/common/sae.c b/src/common/sae.c
index e597bfc1ac..0285f4db53 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -2155,7 +2155,7 @@ static int sae_parse_akm_suite_selector(struct sae_data *sae,
 
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
 		     const u8 **token, size_t *token_len, int *allowed_groups,
-		     int h2e)
+		     int h2e, int *ie_offset)
 {
 	const u8 *pos = data, *end = data + len;
 	u16 res;
@@ -2181,6 +2181,9 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
 	if (res != WLAN_STATUS_SUCCESS)
 		return res;
 
+	if (ie_offset)
+		*ie_offset = pos - data;
+
 	/* Optional Password Identifier element */
 	res = sae_parse_password_identifier(sae, &pos, end);
 	if (res != WLAN_STATUS_SUCCESS)
diff --git a/src/common/sae.h b/src/common/sae.h
index 6a6b0c8241..7b6a083f14 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -136,7 +136,7 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
 		     const struct wpabuf *token, const char *identifier);
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
 		     const u8 **token, size_t *token_len, int *allowed_groups,
-		     int h2e);
+		     int h2e, int *ie_offset);
 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
diff --git a/src/pasn/pasn_initiator.c b/src/pasn/pasn_initiator.c
index a98eba20cf..fd63d7d8f4 100644
--- a/src/pasn/pasn_initiator.c
+++ b/src/pasn/pasn_initiator.c
@@ -108,7 +108,7 @@ static int wpas_pasn_wd_sae_rx(struct pasn_data *pasn, struct wpabuf *wd)
 	}
 
 	res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
-			       1);
+			       1, NULL);
 	if (res != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
 		return -1;
diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c
index ea2737c0f3..d066a0c62a 100644
--- a/src/pasn/pasn_responder.c
+++ b/src/pasn/pasn_responder.c
@@ -85,7 +85,7 @@ static int pasn_wd_handle_sae_commit(struct pasn_data *pasn,
 	}
 
 	res = sae_parse_commit(&pasn->sae, data + 6, buf_len - 6, NULL, 0,
-			       groups, 0);
+			       groups, 0, NULL);
 	if (res != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "PASN: Failed parsing SAE commit");
 		return -1;
diff --git a/tests/fuzzing/sae/sae.c b/tests/fuzzing/sae/sae.c
index 8819a4abbc..74faeeda6f 100644
--- a/tests/fuzzing/sae/sae.c
+++ b/tests/fuzzing/sae/sae.c
@@ -27,10 +27,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
 		return 0;
 
 	os_memset(&sae, 0, sizeof(sae));
-	res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0);
+	res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0, NULL);
 	wpa_printf(MSG_DEBUG, "sae_parse_commit(0): %u", res);
 	sae_clear_data(&sae);
-	res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1);
+	res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1, NULL);
 	wpa_printf(MSG_DEBUG, "sae_parse_commit(1): %u", res);
 	sae_clear_data(&sae);
 	os_program_deinit();
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index e7e7cada9d..f2bd64afc4 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -514,7 +514,8 @@ out:
 
 
 static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
-			     union wpa_event_data *data)
+			     union wpa_event_data *data,
+			     int ie_offset)
 {
 	struct ieee802_11_elems elems;
 	const u8 *mld_addr;
@@ -522,7 +523,8 @@ static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
 	if (!wpa_s->mld)
 		return;
 
-	if (ieee802_11_parse_elems(data->auth.ies, data->auth.ies_len,
+	if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
+				   data->auth.ies_len - ie_offset,
 				   &elems, 0) != ParseOK) {
 		wpa_printf(MSG_DEBUG, "MLD: failed parsing elements");
 		goto out;
@@ -1530,7 +1532,7 @@ static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
 
 static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 			u16 status_code, const u8 *data, size_t len,
-			int external, const u8 *sa)
+			int external, const u8 *sa, int *ie_offset)
 {
 	int *groups;
 
@@ -1594,6 +1596,10 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 			}
 			token_len = elen - 1;
 		}
+
+		if (ie_offset)
+			*ie_offset = token_pos + token_len - data;
+
 		wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
 		wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
 				wpa_s->sme.sae_token);
@@ -1689,7 +1695,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 		res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
 				       groups, status_code ==
 				       WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
-				       status_code == WLAN_STATUS_SAE_PK);
+				       status_code == WLAN_STATUS_SAE_PK,
+				       ie_offset);
 		if (res == SAE_SILENTLY_DISCARD) {
 			wpa_printf(MSG_DEBUG,
 				   "SAE: Drop commit message due to reflection attack");
@@ -1726,6 +1733,10 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 			return -1;
 		if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
 			return -1;
+
+		if (ie_offset && wpa_s->sme.sae.tmp)
+			*ie_offset = 2 + wpa_s->sme.sae.tmp->kck_len;
+
 		wpa_s->sme.sae.state = SAE_ACCEPTED;
 		sae_clear_temp_data(&wpa_s->sme.sae);
 
@@ -1796,7 +1807,7 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
 			wpa_s, le_to_host16(header->u.auth.auth_transaction),
 			le_to_host16(header->u.auth.status_code),
 			header->u.auth.variable,
-			len - auth_length, 1, header->sa);
+			len - auth_length, 1, header->sa, NULL);
 		if (res < 0) {
 			/* Notify failure to the driver */
 			sme_send_external_auth_status(
@@ -1820,6 +1831,7 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 {
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	int ie_offset = 0;
 
 	if (ssid == NULL) {
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
@@ -1864,7 +1876,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 		int res;
 		res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
 				   data->auth.status_code, data->auth.ies,
-				   data->auth.ies_len, 0, data->auth.peer);
+				   data->auth.ies_len, 0, data->auth.peer,
+				   &ie_offset);
 		if (res < 0) {
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
@@ -2004,9 +2017,10 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 	}
 #endif /* CONFIG_FILS */
 
-	/* TODO: Support for other auth_type as well */
-	if (data->auth.auth_type == WLAN_AUTH_OPEN)
-		wpas_sme_ml_auth(wpa_s, data);
+	/* TODO: Support additional auth_type's as well */
+	if (data->auth.auth_type == WLAN_AUTH_OPEN ||
+	    data->auth.auth_type == WLAN_AUTH_SAE)
+		wpas_sme_ml_auth(wpa_s, data, ie_offset);
 
 	sme_associate(wpa_s, ssid->mode, data->auth.peer,
 		      data->auth.auth_type);
-- 
2.25.1




More information about the Hostap mailing list