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 <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-02-12 17:46:33 +02:00 committed by Jouni Malinen
parent d6bfaaac69
commit b64afe22aa
2 changed files with 18 additions and 1 deletions

View file

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

View file

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