SAE: Make sme_sae_auth() return IE offset

Authentication frames include several fixed body parts (see Table 9-68
(Authentication frame body) and Table 9-69 (Presence of fields and
elements in Authentication frames) in IEEE P802.11-REVme/D2.0).

To be able to parse the IE part, these fields need to be skipped. Since
SAE logic already implements this parsing, change SAE authentication
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@intel.com>
This commit is contained in:
Andrei Otcheretianski 2022-12-06 11:46:05 +02:00 committed by Jouni Malinen
parent 870edfd67e
commit 694a1c6873
8 changed files with 38 additions and 18 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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);