From ecea23591350a1eba8f698bf2e999666e9eff64c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 9 Aug 2024 13:46:05 +0530 Subject: [PATCH 1/4] SAE: Check that peer's rejected groups are not enabled in AP Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/sae.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/wpa_supplicant/src/common/sae.c b/components/wpa_supplicant/src/common/sae.c index c18b409969..c93f28ac98 100644 --- a/components/wpa_supplicant/src/common/sae.c +++ b/components/wpa_supplicant/src/common/sae.c @@ -2025,8 +2025,11 @@ static int sae_parse_rejected_groups(struct sae_data *sae, wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", *pos, end - *pos); - if (!sae_is_rejected_groups_elem(*pos, end)) + if (!sae_is_rejected_groups_elem(*pos, end)) { + wpabuf_free(sae->tmp->peer_rejected_groups); + sae->tmp->peer_rejected_groups = NULL; return WLAN_STATUS_SUCCESS; + } epos = *pos; epos++; /* skip IE type */ @@ -2086,6 +2089,9 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, res = sae_parse_rejected_groups(sae, &pos, end); if (res != WLAN_STATUS_SUCCESS) return res; + } else { + wpabuf_free(sae->tmp->peer_rejected_groups); + sae->tmp->peer_rejected_groups = NULL; } /* Optional Anti-Clogging Token Container element */ From 8abeae65ed5491ec01be82865b90572358b5d1ec Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 9 Sep 2024 18:51:10 +0530 Subject: [PATCH 2/4] SAE: Reject invalid Rejected Groups element in the parser There is no need to depend on all uses (i.e., both hostapd and wpa_supplicant) to verify that the length of the Rejected Groups field in the Rejected Groups element is valid (i.e., a multiple of two octets) since the common parser can reject the message when detecting this. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/sae.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/wpa_supplicant/src/common/sae.c b/components/wpa_supplicant/src/common/sae.c index c93f28ac98..77fe281cd4 100644 --- a/components/wpa_supplicant/src/common/sae.c +++ b/components/wpa_supplicant/src/common/sae.c @@ -2039,6 +2039,12 @@ static int sae_parse_rejected_groups(struct sae_data *sae, epos++; /* skip ext ID */ len--; + if (len & 1) { + wpa_printf(MSG_DEBUG, + "SAE: Invalid length of the Rejected Groups element payload: %u", + len); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } wpabuf_free(sae->tmp->peer_rejected_groups); sae->tmp->peer_rejected_groups = wpabuf_alloc(len); if (!sae->tmp->peer_rejected_groups) From 92cf32a40bed851e2e8addcce977f4060f06f596 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 10 Sep 2024 10:22:08 +0530 Subject: [PATCH 3/4] SAE: Check that peer's rejected groups are not enabled Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_wpa3.c | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 4ce92b10d3..7d863493b8 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -172,6 +172,53 @@ static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len) return buf; } +static int wpa3_sae_is_group_enabled(int group) +{ + int *groups = NULL; + int default_groups[] = { 19, 0 }; + int i; + + if (!groups) { + groups = default_groups; + } + + for (i = 0; groups[i] > 0; i++) { + if (groups[i] == group) { + return 1; + } + } + + return 0; +} + +static int wpa3_check_sae_rejected_groups(const struct wpabuf *groups) +{ + size_t i, count; + const u8 *pos; + + if (!groups) { + return 0; + } + + pos = wpabuf_head(groups); + count = wpabuf_len(groups) / 2; + for (i = 0; i < count; i++) { + int enabled; + u16 group; + + group = WPA_GET_LE16(pos); + pos += 2; + enabled = wpa3_sae_is_group_enabled(group); + wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s", + group, enabled ? "enabled" : "disabled"); + if (enabled) { + return 1; + } + } + + return 0; +} + static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status) { int ret; @@ -208,6 +255,9 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status) wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret); return ret; } + if (g_sae_data.tmp && wpa3_check_sae_rejected_groups(g_sae_data.tmp->peer_rejected_groups)) { + return -1; + } ret = sae_process_commit(&g_sae_data); if (ret) { From ae56989c7f5d9965f280ead36a8f7f201c909430 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 10 Sep 2024 10:25:11 +0530 Subject: [PATCH 4/4] SAE: Check for invalid Rejected Groups element length explicitly on STA Instead of practically ignoring an odd octet at the end of the element, check for such invalid case explicitly. This is needed to avoid a potential group downgrade attack. Fixes: 444d76f74f65 ("SAE: Check that peer's rejected groups are not enabled") Signed-off-by: Jouni Malinen --- .../wpa_supplicant/esp_supplicant/src/esp_wpa3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 7d863493b8..d2ed8e4456 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -193,7 +193,7 @@ static int wpa3_sae_is_group_enabled(int group) static int wpa3_check_sae_rejected_groups(const struct wpabuf *groups) { - size_t i, count; + size_t i, count, len; const u8 *pos; if (!groups) { @@ -201,7 +201,14 @@ static int wpa3_check_sae_rejected_groups(const struct wpabuf *groups) } pos = wpabuf_head(groups); - count = wpabuf_len(groups) / 2; + len = wpabuf_len(groups); + if (len & 1) { + wpa_printf(MSG_DEBUG, + "SAE: Invalid length of the Rejected Groups element payload: %zu", + len); + return 1; + } + count = len / 2; for (i = 0; i < count; i++) { int enabled; u16 group;