From b64afe22aa28bec9d08d6de4cba8152591b60639 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Feb 2014 17:46:33 +0200 Subject: [PATCH] Fix SAE state validation on AP Confirm-before-commit validation step allowed execution to continue on error case. This could result in segfault in sae_check_confirm() if the temporary SAE data was not available (as it would not be, e.g., in case of an extra SAE confirm message being received after successful exchange). Fix this by stopping SAE processing immediately after detecting unexpected state for confirm message. In addition, make the public sae.c functions verify sae->tmp before dereferencing it to make this type of bugs less likely to result in critical issues. Signed-hostap: Jouni Malinen --- src/ap/ieee802_11.c | 2 ++ src/common/sae.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 0f678835f..4626ec471 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -471,6 +471,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, HOSTAPD_LEVEL_DEBUG, "SAE confirm before commit"); resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + goto failed; } hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, @@ -502,6 +503,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; } +failed: sta->auth_alg = WLAN_AUTH_SAE; send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, diff --git a/src/common/sae.c b/src/common/sae.c index 08bf054cb..674cb6502 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -503,6 +503,8 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, const u8 *password, size_t password_len, struct sae_data *sae) { + if (sae->tmp == NULL) + return -1; if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, password_len) < 0) return -1; @@ -634,7 +636,8 @@ fail: int sae_process_commit(struct sae_data *sae) { u8 k[SAE_MAX_PRIME_LEN]; - if ((sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || + if (sae->tmp == NULL || + (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || sae_derive_keys(sae, k) < 0) return -1; @@ -646,6 +649,10 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, const struct wpabuf *token) { u8 *pos; + + if (sae->tmp == NULL) + return; + wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ if (token) wpabuf_put_buf(buf, token); @@ -990,6 +997,9 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) { const u8 *sc; + if (sae->tmp == NULL) + return; + /* Send-Confirm */ sc = wpabuf_put(buf, 0); wpabuf_put_le16(buf, sae->send_confirm); @@ -1021,6 +1031,11 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); + if (sae->tmp == NULL) { + wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); + return -1; + } + if (sae->tmp->ec) sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, sae->tmp->peer_commit_element_ecc,