From 4a5f6e88b26bb0c3259b9ac2b23d98909d308000 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 28 Feb 2021 18:39:49 +0200 Subject: [PATCH] SAE: Use more explicit IE payload validation steps This is an attempt of making the code easier to understand for static analyzers. The helper functions were already verifying that these IEs are fully within the memory buffer, but that may not have been clear enough for automated analysis. Signed-off-by: Jouni Malinen --- src/common/sae.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/common/sae.c b/src/common/sae.c index 372905db0..f0d4c228c 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -2023,6 +2023,9 @@ static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos, static int sae_parse_password_identifier(struct sae_data *sae, const u8 **pos, const u8 *end) { + const u8 *epos; + u8 len; + wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", *pos, end - *pos); if (!sae_is_password_id_elem(*pos, end)) { @@ -2037,9 +2040,17 @@ static int sae_parse_password_identifier(struct sae_data *sae, return WLAN_STATUS_SUCCESS; /* No Password Identifier */ } + epos = *pos; + epos++; /* skip IE type */ + len = *epos++; /* IE length */ + if (len > end - epos || len < 1) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + epos++; /* skip ext ID */ + len--; + if (sae->tmp->pw_id && - ((*pos)[1] - 1 != (int) os_strlen(sae->tmp->pw_id) || - os_memcmp(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1) != 0)) { + (len != os_strlen(sae->tmp->pw_id) || + os_memcmp(sae->tmp->pw_id, epos, len) != 0)) { wpa_printf(MSG_DEBUG, "SAE: The included Password Identifier does not match the expected one (%s)", sae->tmp->pw_id); @@ -2047,14 +2058,14 @@ static int sae_parse_password_identifier(struct sae_data *sae, } os_free(sae->tmp->pw_id); - sae->tmp->pw_id = os_malloc((*pos)[1]); + sae->tmp->pw_id = os_malloc(len + 1); if (!sae->tmp->pw_id) return WLAN_STATUS_UNSPECIFIED_FAILURE; - os_memcpy(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1); - sae->tmp->pw_id[(*pos)[1] - 1] = '\0'; + os_memcpy(sae->tmp->pw_id, epos, len); + sae->tmp->pw_id[len] = '\0'; wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier", - sae->tmp->pw_id, (*pos)[1] - 1); - *pos = *pos + 2 + (*pos)[1]; + sae->tmp->pw_id, len); + *pos = epos + len; return WLAN_STATUS_SUCCESS; } @@ -2062,19 +2073,30 @@ static int sae_parse_password_identifier(struct sae_data *sae, static int sae_parse_rejected_groups(struct sae_data *sae, const u8 **pos, const u8 *end) { + const u8 *epos; + u8 len; + wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", *pos, end - *pos); if (!sae_is_rejected_groups_elem(*pos, end)) return WLAN_STATUS_SUCCESS; + + epos = *pos; + epos++; /* skip IE type */ + len = *epos++; /* IE length */ + if (len > end - epos || len < 1) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + epos++; /* skip ext ID */ + len--; + wpabuf_free(sae->tmp->peer_rejected_groups); - sae->tmp->peer_rejected_groups = wpabuf_alloc((*pos)[1] - 1); + sae->tmp->peer_rejected_groups = wpabuf_alloc(len); if (!sae->tmp->peer_rejected_groups) return WLAN_STATUS_UNSPECIFIED_FAILURE; - wpabuf_put_data(sae->tmp->peer_rejected_groups, (*pos) + 3, - (*pos)[1] - 1); + wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len); wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list", sae->tmp->peer_rejected_groups); - *pos = *pos + 2 + (*pos)[1]; + *pos = epos + len; return WLAN_STATUS_SUCCESS; }