diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 490dbcbe9..e53f0dcbe 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1373,7 +1373,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", @@ -1473,7 +1474,8 @@ 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 8aba713f9..a95ae36dc 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 8e78c96f3..d4a196f15 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -2157,7 +2157,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; @@ -2183,6 +2183,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) @@ -2376,7 +2379,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; @@ -2432,6 +2436,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 IEs */ + if (ie_offset) + *ie_offset = 2 + hash_len; + return 0; } diff --git a/src/common/sae.h b/src/common/sae.h index 6a6b0c824..c446da396 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 a98eba20c..1f9a50830 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 e36aa39b8..3b1912df3 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 8819a4abb..738a8f615 100644 --- a/tests/fuzzing/sae/sae.c +++ b/tests/fuzzing/sae/sae.c @@ -27,10 +27,12 @@ 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 7095edbe5..dce8a5563 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1344,7 +1344,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; @@ -1408,6 +1408,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, @@ -1509,7 +1513,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"); @@ -1544,7 +1549,8 @@ 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); @@ -1616,7 +1622,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( @@ -1674,7 +1680,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);