[PATCH v3 1/5] SAE: Make sme_sae_auth() return IE offset

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Dec 6 01:46:05 PST 2022


Authentication frames include several fixed body parts (see tables 9-68
and 9-69) in IEEE802.11-REVme/D1.3.
In order to be able to parse the IE part, these fields should be
skipped. Since SAE logic already implements this parsing, change SAE
auth handling functions to return the offset to the IE part.
This preparation is needed for future MLD patches that need to parse out
the ML related elements in the authentication frames.

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

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 41a0d66a68..c628ba8269 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1350,7 +1350,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",
@@ -1450,7 +1451,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
 				return;
 			}
 
-			if (sae_check_confirm(sta->sae, var, var_len) < 0) {
+			if (sae_check_confirm(sta->sae, var, var_len, NULL) < 0) {
 				resp = WLAN_STATUS_CHALLENGE_FAIL;
 				goto reply;
 			}
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..ebd693cc4c 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)
@@ -2374,7 +2377,8 @@ 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)
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
+		      int *ie_offset)
 {
 	u8 verifier[SAE_MAX_HASH_LEN];
 	size_t hash_len;
@@ -2430,6 +2434,10 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
 		return -1;
 #endif /* CONFIG_SAE_PK */
 
+	/* 2 bytes are for send-confirm, then the hash, followed by IE's */
+	if (ie_offset)
+		*ie_offset = 2 + hash_len;
+
 	return 0;
 }
 
diff --git a/src/common/sae.h b/src/common/sae.h
index 6a6b0c8241..c446da3964 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -136,9 +136,10 @@ 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);
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
+		      int *ie_offset);
 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
 const char * sae_state_txt(enum sae_state state);
 size_t sae_ecc_prime_len_2_hash_len(size_t prime_len);
diff --git a/src/pasn/pasn_initiator.c b/src/pasn/pasn_initiator.c
index a98eba20cf..1f9a508300 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;
@@ -151,7 +151,7 @@ static int wpas_pasn_wd_sae_rx(struct pasn_data *pasn, struct wpabuf *wd)
 		return -1;
 	}
 
-	res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
+	res = sae_check_confirm(&pasn->sae, data + 6, len - 6, NULL);
 	if (res != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
 		return -1;
diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c
index ea2737c0f3..d21ca6437b 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;
@@ -135,7 +135,7 @@ static int pasn_wd_handle_sae_confirm(struct pasn_data *pasn,
 		return -1;
 	}
 
-	res = sae_check_confirm(&pasn->sae, data + 6, buf_len - 6);
+	res = sae_check_confirm(&pasn->sae, data + 6, buf_len - 6, NULL);
 	if (res != WLAN_STATUS_SUCCESS) {
 		wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
 		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 1f5f96be64..f6ace37606 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1328,7 +1328,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;
 
@@ -1392,6 +1392,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);
 		if (!wpa_s->sme.sae_token) {
 			wpa_dbg(wpa_s, MSG_ERROR,
@@ -1493,7 +1497,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");
@@ -1528,7 +1533,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 		wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
 		if (wpa_s->sme.sae.state != SAE_CONFIRMED)
 			return -1;
-		if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
+		if (sae_check_confirm(&wpa_s->sme.sae, data, len, ie_offset) < 0)
 			return -1;
 		wpa_s->sme.sae.state = SAE_ACCEPTED;
 		sae_clear_temp_data(&wpa_s->sme.sae);
@@ -1600,7 +1605,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(
@@ -1658,7 +1663,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,
+				   NULL);
 		if (res < 0) {
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
-- 
2.25.1




More information about the Hostap mailing list