Просмотр исходного кода

Merge branch 'bugfix/wpa3_pmf_memleak_fix_v4.1' into 'release/v4.1'

WPA3 / PMF memory leak fixes (backport v4.1)

See merge request espressif/esp-idf!8695
Jiang Jiang Jian 5 лет назад
Родитель
Сommit
db3d03f9ac

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 4477b34a3eb506a9117c357e27b0b431ebe1d2e6
+Subproject commit 095cf53d13485144f20ceb5dd7475fd2b837c217

+ 170 - 144
components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c

@@ -21,190 +21,216 @@
 
 static struct sae_data g_sae_data;
 static struct wpabuf *g_sae_token = NULL;
+static struct wpabuf *g_sae_commit = NULL;
+static struct wpabuf *g_sae_confirm = NULL;
 int g_allowed_groups[] = { IANA_SECP256R1, 0 };
 
-static struct wpabuf *wpa3_build_sae_commit(u8 *bssid)
+static esp_err_t wpa3_build_sae_commit(u8 *bssid)
 {
-	int default_group = IANA_SECP256R1;
-        struct wpabuf *buf;
-	u32 len = 0;
-	u8 own_addr[ETH_ALEN];
-	const u8 *pw;
+    int default_group = IANA_SECP256R1;
+    u32 len = 0;
+    u8 own_addr[ETH_ALEN];
+    const u8 *pw;
 
     if (wpa_sta_is_cur_pmksa_set()) {
-		wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
-        return NULL;
+        wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
+        return ESP_FAIL;
     }
 
-	if (g_sae_token) {
-		len = wpabuf_len(g_sae_token);
-		goto reuse_data;
-	}
+    if (g_sae_commit) {
+        wpabuf_free(g_sae_commit);
+        g_sae_commit = NULL;
+    }
 
-	memset(&g_sae_data, 0, sizeof(g_sae_data));
-	if (sae_set_group(&g_sae_data, default_group)) {
-		wpa_printf(MSG_ERROR, "wpa3: could not set SAE group %d", default_group);
-		return NULL;
-	}
+    if (g_sae_token) {
+        len = wpabuf_len(g_sae_token);
+        goto reuse_data;
+    }
 
-	esp_wifi_get_macaddr_internal(WIFI_IF_STA, own_addr);
-	if (!bssid) {
-		wpa_printf(MSG_ERROR, "wpa3: cannot prepare SAE commit with no BSSID!");
-		return NULL;
-	}
+    memset(&g_sae_data, 0, sizeof(g_sae_data));
+    if (sae_set_group(&g_sae_data, default_group)) {
+        wpa_printf(MSG_ERROR, "wpa3: could not set SAE group %d", default_group);
+        return ESP_FAIL;
+    }
+
+    esp_wifi_get_macaddr_internal(WIFI_IF_STA, own_addr);
+    if (!bssid) {
+        wpa_printf(MSG_ERROR, "wpa3: cannot prepare SAE commit with no BSSID!");
+        return ESP_FAIL;
+    }
 
-	pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
-	if (sae_prepare_commit(own_addr, bssid, pw, strlen((const char *)pw), NULL, &g_sae_data) < 0) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
-		return NULL;
-	}
+    pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
+    if (sae_prepare_commit(own_addr, bssid, pw, strlen((const char *)pw), NULL, &g_sae_data) < 0) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
+        return ESP_FAIL;
+    }
 
 reuse_data:
-	len += SAE_COMMIT_MAX_LEN;
-	buf = wpabuf_alloc(len);
-	if (!buf) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
-		return NULL;
-	}
-
-	if (sae_write_commit(&g_sae_data, buf, g_sae_token, NULL) != ESP_OK) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
-		wpabuf_free(buf);
-		return NULL;
-	}
-
-	if (g_sae_token) {
-		wpabuf_free(g_sae_token);
-		g_sae_token = NULL;
-	}
-	g_sae_data.state = SAE_COMMITTED;
-
-	return buf;
+    len += SAE_COMMIT_MAX_LEN;
+    g_sae_commit = wpabuf_alloc(len);
+    if (!g_sae_commit) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
+        return ESP_FAIL;
+    }
+
+    if (sae_write_commit(&g_sae_data, g_sae_commit, g_sae_token, NULL) != ESP_OK) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
+        wpabuf_free(g_sae_commit);
+        g_sae_commit = NULL;
+        return ESP_FAIL;
+    }
+
+    if (g_sae_token) {
+        wpabuf_free(g_sae_token);
+        g_sae_token = NULL;
+    }
+    g_sae_data.state = SAE_COMMITTED;
+
+    return ESP_OK;
 }
 
-static struct wpabuf *wpa3_build_sae_confirm(void)
+static esp_err_t wpa3_build_sae_confirm(void)
 {
-        struct wpabuf *buf;
+    if (g_sae_data.state != SAE_COMMITTED)
+        return ESP_FAIL;
 
-	if (g_sae_data.state != SAE_COMMITTED)
-		return NULL;
+    if (g_sae_confirm) {
+        wpabuf_free(g_sae_confirm);
+        g_sae_confirm = NULL;
+    }
 
-	buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
-	if (!buf) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
-		return NULL;
-	}
+    g_sae_confirm = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
+    if (!g_sae_confirm) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
+        return ESP_FAIL;
+    }
 
-	if (sae_write_confirm(&g_sae_data, buf) != ESP_OK) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
-		wpabuf_free(buf);
-		return NULL;
-	}
-	g_sae_data.state = SAE_CONFIRMED;
+    if (sae_write_confirm(&g_sae_data, g_sae_confirm) != ESP_OK) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
+        wpabuf_free(g_sae_confirm);
+        g_sae_confirm = NULL;
+        return ESP_FAIL;
+    }
+    g_sae_data.state = SAE_CONFIRMED;
+
+    return ESP_OK;
+}
+
+void esp_wpa3_free_sae_data(void)
+{
+    if (g_sae_commit) {
+        wpabuf_free(g_sae_commit);
+        g_sae_commit = NULL;
+    }
 
-	return buf;
+    if (g_sae_confirm) {
+        wpabuf_free(g_sae_confirm);
+        g_sae_confirm = NULL;
+    }
+    sae_clear_data(&g_sae_data);
 }
 
 static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, u32 *sae_msg_len)
 {
-        struct wpabuf *buf = NULL;
-
-	switch (sae_msg_type) {
-		case SAE_MSG_COMMIT:
-			buf = wpa3_build_sae_commit(bssid);
-			break;
-		case SAE_MSG_CONFIRM:
-			buf = wpa3_build_sae_confirm();
-			break;
-		default:
-			break;
-	}
-
-	if (buf) {
-		*sae_msg_len = (u32)wpabuf_len(buf);
-		return wpabuf_mhead_u8(buf);
-	} else {
-		return NULL;
+    u8 *buf = NULL;
+
+    switch (sae_msg_type) {
+        case SAE_MSG_COMMIT:
+            if (ESP_OK != wpa3_build_sae_commit(bssid))
+                return NULL;
+            *sae_msg_len = (u32)wpabuf_len(g_sae_commit);
+            buf = wpabuf_mhead_u8(g_sae_commit);
+            break;
+        case SAE_MSG_CONFIRM:
+            if (ESP_OK != wpa3_build_sae_confirm())
+                return NULL;
+            *sae_msg_len = (u32)wpabuf_len(g_sae_confirm);
+            buf = wpabuf_mhead_u8(g_sae_confirm);
+            break;
+        default:
+            break;
     }
+
+    return buf;
 }
 
 static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
 {
-	int ret;
-
-	if (g_sae_data.state != SAE_COMMITTED) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
-			   g_sae_data.state);
-		return ESP_FAIL;
-	}
-
-	if (status == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
-		if (g_sae_token)
-			wpabuf_free(g_sae_token);
-		g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2);
-		return ESP_OK;
-	}
-
-	ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups);
-	if (ret) {
-		wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
-		return ret;
-	}
-
-	ret = sae_process_commit(&g_sae_data);
-	if (ret) {
-		wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
-		return ret;
-	}
-
-	return ESP_OK;
+    int ret;
+
+    if (g_sae_data.state != SAE_COMMITTED) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
+                   g_sae_data.state);
+        return ESP_FAIL;
+    }
+
+    if (status == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
+        if (g_sae_token)
+            wpabuf_free(g_sae_token);
+        g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2);
+        return ESP_OK;
+    }
+
+    ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups);
+    if (ret) {
+        wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
+        return ret;
+    }
+
+    ret = sae_process_commit(&g_sae_data);
+    if (ret) {
+        wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
+        return ret;
+    }
+
+    return ESP_OK;
 }
 
 static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
 {
-	if (g_sae_data.state != SAE_CONFIRMED) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
-			   g_sae_data.state);
-		return ESP_FAIL;
-	}
-
-	if (sae_check_confirm(&g_sae_data, buf, len) != ESP_OK) {
-		wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE confirm");
-		return ESP_FAIL;
-	}
-	g_sae_data.state = SAE_ACCEPTED;
-
-	wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmkid, true);
-	memcpy(esp_wifi_sta_get_ap_info_prof_pmk_internal(), g_sae_data.pmk, PMK_LEN);
-
-	return ESP_OK;
+    if (g_sae_data.state != SAE_CONFIRMED) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
+                   g_sae_data.state);
+        return ESP_FAIL;
+    }
+
+    if (sae_check_confirm(&g_sae_data, buf, len) != ESP_OK) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE confirm");
+        return ESP_FAIL;
+    }
+    g_sae_data.state = SAE_ACCEPTED;
+
+    wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmkid, true);
+    memcpy(esp_wifi_sta_get_ap_info_prof_pmk_internal(), g_sae_data.pmk, PMK_LEN);
+
+    return ESP_OK;
 }
 
 static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type, u16 status)
 {
-	int ret = ESP_OK;
-
-	switch (sae_msg_type) {
-		case SAE_MSG_COMMIT:
-			ret = wpa3_parse_sae_commit(buf, len, status);
-			break;
-		case SAE_MSG_CONFIRM:
-			ret = wpa3_parse_sae_confirm(buf, len);
-			break;
-		default:
-			wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%d)!",
-				   sae_msg_type);
-			ret = ESP_FAIL;
-			break;
-	}
-
-	return ret;
+    int ret = ESP_OK;
+
+    switch (sae_msg_type) {
+        case SAE_MSG_COMMIT:
+            ret = wpa3_parse_sae_commit(buf, len, status);
+            break;
+        case SAE_MSG_CONFIRM:
+            ret = wpa3_parse_sae_confirm(buf, len);
+            esp_wpa3_free_sae_data();
+            break;
+        default:
+            wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%d)!", sae_msg_type);
+            ret = ESP_FAIL;
+            break;
+    }
+
+    return ret;
 }
 
 void esp_wifi_register_wpa3_cb(struct wpa_funcs *wpa_cb)
 {
-	wpa_cb->wpa3_build_sae_msg = wpa3_build_sae_msg;
-	wpa_cb->wpa3_parse_sae_msg = wpa3_parse_sae_msg;
+    wpa_cb->wpa3_build_sae_msg = wpa3_build_sae_msg;
+    wpa_cb->wpa3_parse_sae_msg = wpa3_parse_sae_msg;
 }
 
 #endif /* CONFIG_WPA3_SAE */

+ 1 - 0
components/wpa_supplicant/src/esp_supplicant/esp_wpa3_i.h

@@ -21,6 +21,7 @@
 #ifdef CONFIG_WPA3_SAE
 
 void esp_wifi_register_wpa3_cb(struct wpa_funcs *wpa_cb);
+void esp_wpa3_free_sae_data(void);
 
 #else /* CONFIG_WPA3_SAE */
 

+ 2 - 0
components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c

@@ -26,6 +26,7 @@
 #include "esp_wpas_glue.h"
 #include "esp_hostap.h"
 
+#include "esp_system.h"
 #include "crypto/crypto.h"
 #include "crypto/sha1.h"
 #include "crypto/aes_wrap.h"
@@ -188,6 +189,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
         case WIFI_REASON_AUTH_FAIL:
         case WIFI_REASON_ASSOC_FAIL:
         case WIFI_REASON_CONNECTION_FAIL:
+            esp_wpa3_free_sae_data();
             wpa_sta_clear_curr_pmksa();
             break;
         default: