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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2021-02-28 18:39:49 +02:00
parent 57fec19dab
commit 4a5f6e88b2

View file

@ -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, static int sae_parse_password_identifier(struct sae_data *sae,
const u8 **pos, const u8 *end) const u8 **pos, const u8 *end)
{ {
const u8 *epos;
u8 len;
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos); *pos, end - *pos);
if (!sae_is_password_id_elem(*pos, end)) { 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 */ 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 && if (sae->tmp->pw_id &&
((*pos)[1] - 1 != (int) os_strlen(sae->tmp->pw_id) || (len != os_strlen(sae->tmp->pw_id) ||
os_memcmp(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1) != 0)) { os_memcmp(sae->tmp->pw_id, epos, len) != 0)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"SAE: The included Password Identifier does not match the expected one (%s)", "SAE: The included Password Identifier does not match the expected one (%s)",
sae->tmp->pw_id); sae->tmp->pw_id);
@ -2047,14 +2058,14 @@ static int sae_parse_password_identifier(struct sae_data *sae,
} }
os_free(sae->tmp->pw_id); 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) if (!sae->tmp->pw_id)
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
os_memcpy(sae->tmp->pw_id, (*pos) + 3, (*pos)[1] - 1); os_memcpy(sae->tmp->pw_id, epos, len);
sae->tmp->pw_id[(*pos)[1] - 1] = '\0'; sae->tmp->pw_id[len] = '\0';
wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier", wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier",
sae->tmp->pw_id, (*pos)[1] - 1); sae->tmp->pw_id, len);
*pos = *pos + 2 + (*pos)[1]; *pos = epos + len;
return WLAN_STATUS_SUCCESS; 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, static int sae_parse_rejected_groups(struct sae_data *sae,
const u8 **pos, const u8 *end) const u8 **pos, const u8 *end)
{ {
const u8 *epos;
u8 len;
wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame",
*pos, end - *pos); *pos, end - *pos);
if (!sae_is_rejected_groups_elem(*pos, end)) if (!sae_is_rejected_groups_elem(*pos, end))
return WLAN_STATUS_SUCCESS; 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); 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) if (!sae->tmp->peer_rejected_groups)
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
wpabuf_put_data(sae->tmp->peer_rejected_groups, (*pos) + 3, wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len);
(*pos)[1] - 1);
wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list", wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list",
sae->tmp->peer_rejected_groups); sae->tmp->peer_rejected_groups);
*pos = *pos + 2 + (*pos)[1]; *pos = epos + len;
return WLAN_STATUS_SUCCESS; return WLAN_STATUS_SUCCESS;
} }