]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Add processing of the confirm message
authorJouni Malinen <j@w1.fi>
Sun, 30 Dec 2012 20:31:19 +0000 (22:31 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 12 Jan 2013 15:51:52 +0000 (17:51 +0200)
This adds validation of the received confirm messages for SAE.

Signed-hostap: Jouni Malinen <j@w1.fi>

src/ap/ieee802_11.c
src/common/sae.c
src/common/sae.h
wpa_supplicant/sme.c

index 8deb3f358c2310712e175c508f4a62c3babbe677..3ecac91083b5026b61beaae448a7627c26f9f2cd 100644 (file)
@@ -365,22 +365,6 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
 }
 
 
-static u16 handle_sae_confirm(struct hostapd_data *hapd, struct sta_info *sta,
-                             const u8 *data, size_t len)
-{
-       u16 rc;
-
-       wpa_hexdump(MSG_DEBUG, "SAE confirm fields", data, len);
-
-       if (len < 2)
-               return WLAN_STATUS_UNSPECIFIED_FAILURE;
-       rc = WPA_GET_LE16(data);
-       wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
-
-       return WLAN_STATUS_SUCCESS;
-}
-
-
 static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                            const struct ieee80211_mgmt *mgmt, size_t len,
                            u8 auth_transaction)
@@ -418,10 +402,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                               HOSTAPD_LEVEL_DEBUG,
                               "SAE authentication (RX confirm)");
-               resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
-                                         ((u8 *) mgmt) + len -
-                                         mgmt->u.auth.variable);
-               if (resp == WLAN_STATUS_SUCCESS) {
+               if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
+                                      ((u8 *) mgmt) + len -
+                                      mgmt->u.auth.variable) < 0) {
+                       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+               } else {
+                       resp = WLAN_STATUS_SUCCESS;
                        sta->flags |= WLAN_STA_AUTH;
                        wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
                        sta->auth_alg = WLAN_AUTH_SAE;
index 0adf0c011676d464728e2950dd39cd32973d9673..19aa7afca00e39ba1eab9178ed8251f546c4c417 100644 (file)
@@ -574,3 +574,51 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
        hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, len,
                           wpabuf_put(buf, SHA256_MAC_LEN));
 }
+
+
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
+{
+       u16 rc;
+       const u8 *addr[5];
+       size_t elen[5];
+       u8 verifier[SHA256_MAC_LEN];
+
+       wpa_hexdump(MSG_DEBUG, "SAE: Confirm fields", data, len);
+
+       if (len < 2 + SHA256_MAC_LEN) {
+               wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
+               return -1;
+       }
+
+       rc = WPA_GET_LE16(data);
+       wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
+
+       /* Confirm
+        * CN(key, X, Y, Z, ...) =
+        *    HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
+        * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
+        *               PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
+        */
+       addr[0] = data;
+       elen[0] = 2;
+       addr[1] = sae->peer_commit_scalar;
+       elen[1] = 32;
+       addr[2] = sae->peer_commit_element;
+       elen[2] = 2 * 32;
+       addr[3] = sae->own_commit_scalar;
+       elen[3] = 32;
+       addr[4] = sae->own_commit_element;
+       elen[4] = 2 * 32;
+       hmac_sha256_vector(sae->kck, sizeof(sae->kck), 5, addr, elen, verifier);
+
+       if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
+               wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
+               wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
+                           data + 2, SHA256_MAC_LEN);
+               wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
+                           verifier, SHA256_MAC_LEN);
+               return -1;
+       }
+
+       return 0;
+}
index 7b5a1241cf7eec959a83ac07ef6ebfd5cff24f9b..bfefd5da601cb566d40857112f3ded05773e2b1b 100644 (file)
@@ -32,5 +32,6 @@ int sae_process_commit(struct sae_data *sae);
 void sae_write_commit(struct sae_data *sae, struct wpabuf *buf);
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len);
 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
+int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
 
 #endif /* SAE_H */
index a4a29dc9e18ac54cf5d83c821a0974255fbc633e..870313dae553a108d557af285e640145ef890da2 100644 (file)
@@ -399,21 +399,6 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_SAE
 
-static int sme_sae_process_confirm(struct wpa_supplicant *wpa_s, const u8 *data,
-                                  size_t len)
-{
-       u16 rc;
-
-       if (len < 2)
-               return -1;
-       rc = WPA_GET_LE16(data);
-       wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
-
-       /* TODO */
-       return 0;
-}
-
-
 static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                        u16 status_code, const u8 *data, size_t len)
 {
@@ -448,7 +433,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
                if (wpa_s->sme.sae.state != SAE_CONFIRM)
                        return -1;
-               if (sme_sae_process_confirm(wpa_s, data, len) < 0)
+               if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
                        return -1;
                return 1;
        }