]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Fix SAE state validation on AP
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 12 Feb 2014 15:46:33 +0000 (17:46 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 12 Feb 2014 15:46:33 +0000 (17:46 +0200)
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>

src/ap/ieee802_11.c
src/common/sae.c

index 0f678835f90cdee787dd0e1e29f855ef1a6f1b46..4626ec471e7d86abd7c2d4a7667a3fe5e44416fb 100644 (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,
index 08bf054cbd133166c8a2d45524ab6bb1d8cc35ea..674cb650208d00d183010ee513caa066bae40092 100644 (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,