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

Merge branch 'feature/sae_sta_h2e' into 'master'

SAE H2E support for STA

See merge request espressif/esp-idf!17860
Jiang Jiang Jian 3 лет назад
Родитель
Сommit
5f9bbf71fe
24 измененных файлов с 1500 добавлено и 174 удалено
  1. 0 1
      components/esp_rom/esp32c2/ld/esp32c2.rom.ld
  2. 2 1
      components/esp_wifi/include/esp_wifi_types.h
  3. 1 1
      components/esp_wifi/lib
  4. 48 0
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c
  5. 11 0
      components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c
  6. 79 73
      components/wpa_supplicant/esp_supplicant/src/esp_common.c
  7. 4 0
      components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h
  8. 41 18
      components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c
  9. 2 0
      components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c
  10. 8 0
      components/wpa_supplicant/src/common/ieee802_11_defs.h
  11. 866 57
      components/wpa_supplicant/src/common/sae.c
  12. 38 5
      components/wpa_supplicant/src/common/sae.h
  13. 21 1
      components/wpa_supplicant/src/common/wpa_common.c
  14. 3 0
      components/wpa_supplicant/src/common/wpa_common.h
  15. 35 0
      components/wpa_supplicant/src/crypto/crypto.h
  16. 92 3
      components/wpa_supplicant/src/rsn_supp/wpa.c
  17. 4 0
      components/wpa_supplicant/src/rsn_supp/wpa.h
  18. 5 2
      components/wpa_supplicant/src/rsn_supp/wpa_i.h
  19. 35 0
      components/wpa_supplicant/src/rsn_supp/wpa_ie.c
  20. 3 1
      components/wpa_supplicant/src/rsn_supp/wpa_ie.h
  21. 191 0
      components/wpa_supplicant/src/utils/const_time.h
  22. 10 10
      components/wpa_supplicant/test/test_sae.c
  23. 1 0
      examples/wifi/getting_started/station/main/station_example_main.c
  24. 0 1
      tools/ci/check_copyright_ignore.txt

+ 0 - 1
components/esp_rom/esp32c2/ld/esp32c2.rom.ld

@@ -2106,7 +2106,6 @@ sta_recv_mgmt = 0x40002094;
 ieee80211_send_setup = 0x40002098;
 ieee80211_send_probereq = 0x4000209c;
 sta_auth_shared = 0x400020a4;
-sta_auth_sae = 0x400020a8;
 cnx_coexist_timeout_process = 0x400020ac;
 ieee80211_alloc_challenge = 0x400020b0;
 cnx_assoc_timeout = 0x400020b4;

+ 2 - 1
components/esp_wifi/include/esp_wifi_types.h

@@ -254,7 +254,8 @@ typedef struct {
     uint32_t mbo_enabled:1;       /**< Whether MBO is enabled for the connection */
     uint32_t ft_enabled:1;        /**< Whether FT is enabled for the connection */
     uint32_t owe_enabled:1;       /**< Whether OWE is enabled for the connection */
-    uint32_t reserved:27;         /**< Reserved for future feature set */
+    uint32_t sae_pwe_h2e:2;       /**< Whether SAE hash to element is enabled */
+    uint32_t reserved:25;         /**< Reserved for future feature set */
 } wifi_sta_config_t;
 
 /** @brief Configuration data for ESP32 AP or STA.

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 81ab3ab615a7b7741a466958b90f38cdb9413ad2
+Subproject commit ec0327abd2d420062224d3a741f3cfd394bd8aae

+ 48 - 0
components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c

@@ -46,6 +46,21 @@ cleanup:
 }
 
 
+struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
+{
+
+    mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
+    if (bn == NULL) {
+        return NULL;
+    }
+
+    mbedtls_mpi_init(bn);
+    mbedtls_mpi_lset(bn, val);
+
+    return (struct crypto_bignum *)bn;
+}
+
+
 void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
 {
     mbedtls_mpi_free((mbedtls_mpi *)n);
@@ -163,6 +178,39 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
 }
 
 
+int crypto_bignum_sqrmod(const struct crypto_bignum *a,
+                         const struct crypto_bignum *b,
+                         struct crypto_bignum *c)
+{
+    int res;
+    struct crypto_bignum *tmp = crypto_bignum_init();
+    if (!tmp) {
+        return -1;
+    }
+
+    res = mbedtls_mpi_copy((mbedtls_mpi *) tmp,(const mbedtls_mpi *) a);
+    res = crypto_bignum_mulmod(a,tmp,b,c);
+
+    crypto_bignum_deinit(tmp, 0);
+    return res ? -1 : 0;
+}
+
+
+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
+                         struct crypto_bignum *r)
+{
+    int res;
+    res = mbedtls_mpi_copy((mbedtls_mpi *) r,(const mbedtls_mpi *) a);
+    if (res) {
+        return -1;
+    }
+
+    res = mbedtls_mpi_shift_r((mbedtls_mpi *)r, n);
+    return res ? -1 : 0;
+
+}
+
+
 int crypto_bignum_cmp(const struct crypto_bignum *a,
                       const struct crypto_bignum *b)
 {

+ 11 - 0
components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c

@@ -115,6 +115,11 @@ size_t crypto_ec_prime_len(struct crypto_ec *e)
 	return mbedtls_mpi_size(&e->group.P);
 }
 
+size_t crypto_ec_order_len(struct crypto_ec *e)
+{
+	return mbedtls_mpi_size(&e->group.N);
+}
+
 
 size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
 {
@@ -152,6 +157,12 @@ const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
 }
 
 
+const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
+{
+	return (const struct crypto_bignum *) &e->group.B;
+}
+
+
 void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
 {
 	mbedtls_ecp_point_free((mbedtls_ecp_point *) p);

+ 79 - 73
components/wpa_supplicant/esp_supplicant/src/esp_common.c

@@ -57,7 +57,7 @@ static int handle_action_frm(u8 *frame, size_t len,
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_SUPPLICANT_TASK */
 
 #if defined(CONFIG_WPA_11KV_SUPPORT)
 static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
@@ -99,7 +99,7 @@ static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, u32 rssi, u8 channe
 
 	return 0;
 }
-#endif
+#endif /* defined(CONFIG_WPA_11KV_SUPPORT) */
 
 #ifdef CONFIG_SUPPLICANT_TASK
 static void btm_rrm_task(void *pvParameters)
@@ -153,7 +153,7 @@ static void btm_rrm_task(void *pvParameters)
 	/* At this point, we completed */
 	os_task_delete(NULL);
 }
-#endif
+#endif /* CONFIG_SUPPLICANT_TASK */
 
 static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
 {
@@ -192,7 +192,7 @@ static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
 
 	if (wpa_s->subtype)
 		wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION;
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 
 #ifdef CONFIG_IEEE80211R
 	/* register auth/assoc frames if FT is enabled */
@@ -200,7 +200,7 @@ static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
 		wpa_s->type |= (1 << WLAN_FC_STYPE_AUTH) |
 				(1 << WLAN_FC_STYPE_ASSOC_RESP) |
 				(1 << WLAN_FC_STYPE_REASSOC_RESP);
-#endif
+#endif /* CONFIG_IEEE80211R */
 	esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
 }
 
@@ -240,7 +240,7 @@ static void supplicant_sta_disconn_handler(void* arg, esp_event_base_t event_bas
 #ifdef CONFIG_WPA_11KV_SUPPORT
 	wpas_rrm_reset(wpa_s);
 	wpas_clear_beacon_rep_data(wpa_s);
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 	if (wpa_s->current_bss) {
 		wpa_s->current_bss = NULL;
 	}
@@ -280,7 +280,7 @@ static int handle_assoc_frame(u8 *frame, size_t len,
 	}
 	return 0;
 }
-#endif
+#endif /* CONFIG_IEEE80211R */
 
 static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
 				   u32 rssi, u8 channel, u64 current_tsf)
@@ -300,16 +300,16 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
 	case WLAN_FC_STYPE_REASSOC_RESP:
 		ret = handle_assoc_frame(frame, len, sender, rssi, channel);
 		break;
-#endif
+#endif /* CONFIG_IEEE80211R */
 #if defined(CONFIG_WPA_11KV_SUPPORT)
 	case WLAN_FC_STYPE_ACTION:
 #ifdef CONFIG_SUPPLICANT_TASK
 		ret = handle_action_frm(frame, len, sender, rssi, channel);
-#else
+#else /* CONFIG_SUPPLICANT_TASK */
 		ret = mgmt_rx_action(frame, len, sender, rssi, channel);
-#endif
+#endif /* CONFIG_SUPPLICANT_TASK */
 		break;
-#endif
+#endif /* defined(CONFIG_WPA_11KV_SUPPORT) */
 	default:
 		ret = -1;
 		break;
@@ -341,7 +341,7 @@ bool mbo_bss_profile_match(u8 *bssid)
 
 	return true;
 }
-#endif
+#endif /* CONFIG_MBO */
 
 int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
 {
@@ -369,11 +369,11 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
 		ret = -1;
 		goto err;
 	}
-#endif
+#endif /* CONFIG_SUPPLICANT_TASK */
 #ifdef CONFIG_WPA_11KV_SUPPORT
 	wpas_rrm_reset(wpa_s);
 	wpas_clear_beacon_rep_data(wpa_s);
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 	esp_scan_init(wpa_s);
 
 	esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
@@ -385,7 +385,7 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
 	wpa_s->subtype = 0;
 #ifdef CONFIG_IEEE80211R
 	wpa_s->type |= (1 << WLAN_FC_STYPE_ASSOC_RESP) | (1 << WLAN_FC_STYPE_REASSOC_RESP) | (1 << WLAN_FC_STYPE_AUTH);
-#endif
+#endif /* CONFIG_IEEE80211R */
 	if (esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype) != ESP_OK) {
 		ret = -1;
 		goto err;
@@ -393,7 +393,7 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
 	wpa_cb->wpa_sta_rx_mgmt = ieee80211_handle_rx_frm;
 #ifdef CONFIG_MBO
 	dl_list_init(&wpa_s->bss_tmp_disallowed);
-#endif
+#endif /* CONFIG_MBO */
 	return 0;
 err:
 	esp_supplicant_common_deinit();
@@ -408,7 +408,7 @@ void esp_supplicant_common_deinit(void)
 #ifdef CONFIG_WPA_11KV_SUPPORT
 	wpas_rrm_reset(wpa_s);
 	wpas_clear_beacon_rep_data(wpa_s);
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 	esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
 			&supplicant_sta_conn_handler);
 	esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
@@ -428,7 +428,7 @@ void esp_supplicant_common_deinit(void)
 			s_supplicant_api_lock = NULL;
 		}
 	}
-#endif
+#endif /* CONFIG_SUPPLICANT_TASK */
 }
 
 #ifdef CONFIG_WPA_11KV_SUPPORT
@@ -555,7 +555,7 @@ static size_t get_rm_enabled_ie(uint8_t *ie, size_t len)
 	*pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
 #ifdef SCAN_CACHE_SUPPORTED
 		WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
-#endif
+#endif /* SCAN_CACHE_SUPPORTED */
 		WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
 
 	os_memcpy(ie, rrm_ie, sizeof(rrm_ie));
@@ -618,7 +618,7 @@ static uint8_t get_operating_class_ie(uint8_t *ie, size_t len)
 
 	return op_class_ie_len + 2;
 }
-#endif
+#endif /* CONFIG_MBO */
 
 static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
 {
@@ -642,7 +642,7 @@ static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
 	return ext_caps_ie_len + 2;
 }
 
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 
 void esp_set_scan_ie(void)
 {
@@ -664,12 +664,12 @@ void esp_set_scan_ie(void)
 	ie_len = get_mbo_oce_scan_ie(pos, len);
 	pos += ie_len;
 	len -= ie_len;
-#endif
+#endif /* CONFIG_MBO */
 	esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ);
 	esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0);
 	os_free(ie);
 #undef SCAN_IE_LEN
-#endif
+#endif /* CONFIG_WPA_11KV_SUPPORT */
 }
 
 #ifdef CONFIG_IEEE80211R
@@ -703,52 +703,8 @@ static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len)
 
 	return mdie_len;
 }
-#endif
+#endif /* CONFIG_IEEE80211R */
 
-void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
-{
-#define ASSOC_IE_LEN 128
-	uint8_t *ie, *pos;
-	size_t len = ASSOC_IE_LEN, ie_len;
-
-	ie = os_malloc(ASSOC_IE_LEN + ies_len);
-	if (!ie) {
-		wpa_printf(MSG_ERROR, "failed to allocate ie");
-		return;
-	}
-	pos = ie;
-#ifdef CONFIG_WPA_11KV_SUPPORT
-	ie_len = get_extended_caps_ie(pos, len);
-	pos += ie_len;
-	len -= ie_len;
-	ie_len = get_rm_enabled_ie(pos, len);
-	pos += ie_len;
-	len -= ie_len;
-#ifdef CONFIG_MBO
-	ie_len = get_operating_class_ie(pos, len);
-	pos += ie_len;
-	len -= ie_len;
-	ie_len = get_mbo_oce_assoc_ie(pos, len);
-	pos += ie_len;
-	len -= ie_len;
-#endif
-#endif
-#ifdef CONFIG_IEEE80211R
-	if (mdie) {
-		ie_len = add_mdie(bssid, pos, len);
-		pos += ie_len;
-		len -= ie_len;
-	}
-#endif
-	if (ies_len) {
-		os_memcpy(pos, ies, ies_len);
-		pos += ies_len;
-		len -= ies_len;
-	}
-	esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_REQ, ie, ASSOC_IE_LEN - len, 0);
-	os_free(ie);
-#undef ASSOC_IE_LEN
-}
 
 #ifdef CONFIG_IEEE80211R
 int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
@@ -768,7 +724,7 @@ int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
 
 	return 0;
 }
-#endif
+#endif /* CONFIG_IEEE80211R */
 
 void esp_get_tx_power(uint8_t *tx_power)
 {
@@ -846,8 +802,8 @@ int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
 	}
 	return 0;
 }
-#endif
-#else
+#endif /* CONFIG_SUPPLICANT_TASK */
+#else /* defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R) */
 int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
 				      void *cb_ctx)
 {
@@ -866,11 +822,61 @@ int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
 	return -1;
 }
 void esp_set_scan_ie(void) { }
-void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
 int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
 {
 	wpa_cb->wpa_sta_rx_mgmt = NULL;
 	return 0;
 }
 void esp_supplicant_common_deinit(void) { }
-#endif
+#endif /* defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R) */
+
+#if defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE)
+void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
+{
+#define ASSOC_IE_LEN 128
+	uint8_t *ie, *pos;
+	size_t len = ASSOC_IE_LEN;
+#if defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R)
+    size_t ie_len;
+#endif /* defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R) */
+	ie = os_malloc(ASSOC_IE_LEN + ies_len);
+	if (!ie) {
+		wpa_printf(MSG_ERROR, "failed to allocate ie");
+		return;
+	}
+	pos = ie;
+#ifdef CONFIG_WPA_11KV_SUPPORT
+	ie_len = get_extended_caps_ie(pos, len);
+	pos += ie_len;
+	len -= ie_len;
+	ie_len = get_rm_enabled_ie(pos, len);
+	pos += ie_len;
+	len -= ie_len;
+#ifdef CONFIG_MBO
+	ie_len = get_operating_class_ie(pos, len);
+	pos += ie_len;
+	len -= ie_len;
+	ie_len = get_mbo_oce_assoc_ie(pos, len);
+	pos += ie_len;
+	len -= ie_len;
+#endif /* CONFIG_MBO */
+#endif /* CONFIG_WPA_11KV_SUPPORT */
+#ifdef CONFIG_IEEE80211R
+	if (mdie) {
+		ie_len = add_mdie(bssid, pos, len);
+		pos += ie_len;
+		len -= ie_len;
+	}
+#endif /* CONFIG_IEEE80211R */
+	if (ies_len) {
+		os_memcpy(pos, ies, ies_len);
+		pos += ies_len;
+		len -= ies_len;
+	}
+	esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_REQ, ie, ASSOC_IE_LEN - len, 0);
+	os_free(ie);
+#undef ASSOC_IE_LEN
+}
+#else
+void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
+#endif  /* defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */

+ 4 - 0
components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h

@@ -111,6 +111,7 @@ typedef struct {
     size_t num_pmkid;
     const u8 *pmkid;
     int mgmt_group_cipher;
+    uint8_t rsnxe_capa;
 } wifi_wpa_ie_t;
 
 struct wpa_funcs {
@@ -137,6 +138,7 @@ struct wpa_funcs {
     void (*wpa_config_done)(void);
     uint8_t *(*owe_build_dhie)(uint16_t group);
     int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len);
+    int (*wpa_sta_set_ap_rsnxe)(const u8 *rsnxe, size_t rsnxe_ie_len);
 };
 
 struct wpa2_funcs {
@@ -277,5 +279,7 @@ esp_err_t esp_wifi_remain_on_channel(uint8_t ifx, uint8_t type, uint8_t channel,
 bool esp_wifi_is_mbo_enabled_internal(uint8_t if_index);
 void esp_wifi_get_pmf_config_internal(wifi_pmf_config_t *pmf_cfg, uint8_t ifx);
 bool esp_wifi_is_ft_enabled_internal(uint8_t if_index);
+uint8_t esp_wifi_get_config_sae_pwe_h2e_internal(void);
+uint8_t esp_wifi_get_use_h2e_internal(void);
 
 #endif /* _ESP_WIFI_DRIVER_H_ */

+ 41 - 18
components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c

@@ -1,16 +1,8 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #ifdef CONFIG_WPA3_SAE
 
@@ -19,6 +11,7 @@
 #include "esp_wifi_driver.h"
 #include "rsn_supp/wpa.h"
 
+static struct sae_pt *g_sae_pt;
 static struct sae_data g_sae_data;
 static struct wpabuf *g_sae_token = NULL;
 static struct wpabuf *g_sae_commit = NULL;
@@ -30,7 +23,13 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid)
     int default_group = IANA_SECP256R1;
     u32 len = 0;
     u8 own_addr[ETH_ALEN];
-    const u8 *pw;
+    const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
+    struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
+    uint8_t use_pt = esp_wifi_get_use_h2e_internal();
+
+    if (use_pt && !g_sae_pt) {
+        g_sae_pt = sae_derive_pt(g_allowed_groups, ssid->ssid, ssid->len, pw, strlen((const char *)pw), NULL);
+    }
 
     if (wpa_sta_cur_pmksa_matches_akm()) {
         wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
@@ -59,8 +58,16 @@ static esp_err_t wpa3_build_sae_commit(u8 *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) {
+    if (use_pt &&
+            sae_prepare_commit_pt(&g_sae_data, g_sae_pt,
+                    own_addr, bssid, NULL) < 0) {
+        wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
+        return ESP_FAIL;
+    }
+    if (!use_pt &&
+            sae_prepare_commit(own_addr, bssid, pw,
+                    strlen((const char *)pw),
+                    &g_sae_data) < 0) {
         wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
         return ESP_FAIL;
     }
@@ -128,6 +135,10 @@ void esp_wpa3_free_sae_data(void)
         g_sae_confirm = NULL;
     }
     sae_clear_data(&g_sae_data);
+    if (g_sae_pt) {
+        sae_deinit_pt(g_sae_pt);
+        g_sae_pt = NULL;
+    }
 }
 
 static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len)
@@ -167,11 +178,23 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
     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);
+        if (g_sae_data.h2e) {
+            if ((buf[2] != WLAN_EID_EXTENSION) ||
+                (buf[3] == 0) ||
+                (buf[3] > len - 4) ||
+                (buf[4] != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN)) {
+                wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token container header");
+                return ESP_FAIL;
+            }
+            g_sae_token = wpabuf_alloc_copy(buf + 5, len - 5);
+        } else {
+            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);
+    ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups,
+                           status == WLAN_STATUS_SAE_HASH_TO_ELEMENT);
     if (ret) {
         wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
         return ret;

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

@@ -220,6 +220,7 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t
     data->capabilities = ie.capabilities;
     data->pmkid = ie.pmkid;
     data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher);
+    data->rsnxe_capa = ie.rsnxe_capa;
 
     return ret;
 }
@@ -341,6 +342,7 @@ int esp_supplicant_init(void)
     wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
     wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
     wpa_cb->wpa_config_done = wpa_config_done;
+    wpa_cb->wpa_sta_set_ap_rsnxe = wpa_sm_set_ap_rsnxe;
 
     esp_wifi_register_wpa3_cb(wpa_cb);
 #ifdef CONFIG_OWE_STA

+ 8 - 0
components/wpa_supplicant/src/common/ieee802_11_defs.h

@@ -157,6 +157,7 @@
 #define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99
 #define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
 #define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
+#define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
 
 /* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
 #define WLAN_REASON_UNSPECIFIED 1
@@ -228,6 +229,7 @@
 #define WLAN_EID_FILS_INDICATION 240
 #define WLAN_EID_DILS 241
 #define WLAN_EID_FRAGMENT 242
+#define WLAN_EID_RSNX 244
 #define WLAN_EID_EXTENSION 255
 
 /* Element ID Extension (EID 255) values */
@@ -249,6 +251,12 @@
 #define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
 #define WLAN_EID_EXT_HE_CAPABILITIES 35
 #define WLAN_EID_EXT_HE_OPERATION 36
+#define WLAN_EID_EXT_REJECTED_GROUPS 92
+#define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93
+
+/* Extended RSN Capabilities */
+/* bits 0-3: Field length (n-1) */
+#define WLAN_RSNX_CAPAB_SAE_H2E 5
 
 #define WLAN_EXT_CAPAB_BSS_TRANSITION 19
 

Разница между файлами не показана из-за своего большого размера
+ 866 - 57
components/wpa_supplicant/src/common/sae.c


+ 38 - 5
components/wpa_supplicant/src/common/sae.h

@@ -21,8 +21,9 @@
 #define SAE_KEYSEED_KEY_LEN 32
 #define SAE_MAX_PRIME_LEN 512
 #define SAE_MAX_ECC_PRIME_LEN 66
-#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN)
-#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN)
+#define SAE_MAX_HASH_LEN 64
+#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN + 255)
+#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN)
 
 /* Special value returned by sae_parse_commit() */
 #define SAE_SILENTLY_DISCARD 65535
@@ -45,6 +46,20 @@ struct sae_temporary_data {
 	struct crypto_bignum *prime_buf;
 	struct crypto_bignum *order_buf;
 	char *pw_id;
+	int order_len;
+	struct wpabuf *own_rejected_groups;
+	struct wpabuf *peer_rejected_groups;
+	unsigned int own_addr_higher:1;
+};
+
+struct sae_pt {
+	struct sae_pt *next;
+	int group;
+	struct crypto_ec *ec;
+	struct crypto_ec_point *ecc_pt;
+
+	const struct dh_group *dh;
+	struct crypto_bignum *ffc_pt;
 };
 
 enum {
@@ -66,6 +81,8 @@ struct sae_data {
 	unsigned int sync; /* protocol instance variable: Sync */
 	u16 rc; /* protocol instance variable: Rc (received send-confirm) */
 	struct sae_temporary_data *tmp;
+	struct crypto_bignum *peer_commit_scalar_accepted;
+	unsigned int h2e:1;
 };
 
 int sae_set_group(struct sae_data *sae, int group);
@@ -74,16 +91,32 @@ void sae_clear_data(struct sae_data *sae);
 
 int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
 		       const u8 *password, size_t password_len,
-		       const char *identifier, struct sae_data *sae);
+		       struct sae_data *sae);
+int sae_prepare_commit_pt(struct sae_data *sae, struct sae_pt *pt,
+			  const u8 *addr1, const u8 *addr2,
+			  int *rejected_groups);
 int sae_process_commit(struct sae_data *sae);
 int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
-		      const struct wpabuf *token, const char *identifier);
+		     const struct wpabuf *token, const char *identifier);
 u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
-		     const u8 **token, size_t *token_len, int *allowed_groups);
+		     const u8 **token, size_t *token_len, int *allowed_groups,
+		     int h2e);
 int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
 u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
 const char * sae_state_txt(enum sae_state state);
+size_t sae_ecc_prime_len_2_hash_len(size_t prime_len);
+size_t sae_ffc_prime_len_2_hash_len(size_t prime_len);
+struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len,
+			      const u8 *password, size_t password_len,
+			      const char *identifier);
+struct crypto_ec_point *
+sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
+			   const u8 *addr1, const u8 *addr2);
+struct crypto_bignum *
+sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
+			   const u8 *addr1, const u8 *addr2);
+void sae_deinit_pt(struct sae_pt *pt);
 
 #endif /* SAE_H */
 #endif /* CONFIG_WPA3_SAE */

+ 21 - 1
components/wpa_supplicant/src/common/wpa_common.c

@@ -365,6 +365,25 @@ int wpa_cipher_valid_mgmt_group(int cipher)
 		cipher == WPA_CIPHER_BIP_GMAC_256;
 }
 
+int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
+             struct wpa_ie_data *data)
+{
+	uint8_t rsnxe_capa = 0;
+	uint8_t sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal();
+	memset(data, 0, sizeof(*data));
+
+	if (rsnxe_ie_len < 1) {
+		return -1;
+	}
+	rsnxe_capa = rsnxe_ie[2];
+	if (sae_pwe == 1 && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))){
+		wpa_printf(MSG_ERROR, "SAE H2E required, but not supported by the AP");
+		return -1;
+	}
+	data->rsnxe_capa = rsnxe_capa;
+	return 0;
+}
+
 /**
  * wpa_parse_wpa_ie_rsn - Parse RSN IE
  * @rsn_ie: Buffer containing RSN IE
@@ -941,7 +960,8 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
 		    ie1d.group_cipher == ie2d.group_cipher &&
 		    ie1d.key_mgmt == ie2d.key_mgmt &&
 		    ie1d.capabilities == ie2d.capabilities &&
-		    ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
+		    ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher &&
+		    ie1d.rsnxe_capa == ie2d.rsnxe_capa)
 			return 0;
 	}
 #endif /* CONFIG_IEEE80211R */

+ 3 - 0
components/wpa_supplicant/src/common/wpa_common.h

@@ -337,6 +337,7 @@ struct wpa_ie_data {
 	size_t num_pmkid;
 	const u8 *pmkid;
 	int mgmt_group_cipher;
+	uint8_t rsnxe_capa;
 };
 
 struct rsn_sppamsdu_sup {
@@ -372,6 +373,8 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
 			 struct wpa_ie_data *data);
 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
 		     struct wpa_ie_data *data);
+int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
+			    struct wpa_ie_data *data);
 
 int wpa_compare_rsn_ie(int ft_initial_assoc,
 		       const u8 *ie1, size_t ie1len,

+ 35 - 0
components/wpa_supplicant/src/crypto/crypto.h

@@ -654,6 +654,26 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
 			 const struct crypto_bignum *c,
 			 struct crypto_bignum *d);
 
+/**
+ * crypto_bignum_sqrmod - c = a^2 (mod b)
+ * @a: Bignum
+ * @b: Bignum
+ * @c: Bignum; used to store the result of a^2 % b
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_sqrmod(const struct crypto_bignum *a,
+			  const struct crypto_bignum *b,
+			  struct crypto_bignum *c);
+/**
+ * crypto_bignum_rshift - r = a >> n
+ * @a: Bignum
+ * @n: Number of bits
+ * @r: Bignum; used to store the result of a >> n
+ * Returns: 0 on success, -1 on failure
+ */
+int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
+			  struct crypto_bignum *r);
+
 /**
  * crypto_bignum_cmp - Compare two bignums
  * @a: Bignum
@@ -730,6 +750,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e);
  */
 size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
 
+/**
+ * crypto_ec_order_len - Get length of the order in octets
+ * @e: EC context from crypto_ec_init()
+ * Returns: Length of the order defining the group
+ */
+size_t crypto_ec_order_len(struct crypto_ec *e);
+
 /**
  * crypto_ec_get_prime - Get prime defining an EC group
  * @e: EC context from crypto_ec_init()
@@ -750,6 +777,14 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e);
  * Internal data structure for EC implementation to represent a point. The
  * contents is specific to the used crypto library.
  */
+
+/**
+ * crypto_ec_get_b - Get 'b' coeffiecient of an EC group's curve
+ * @e: EC context from crypto_ec_init()
+ * Returns: 'b' coefficient (bignum) of the group
+ */
+const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e);
+
 struct crypto_ec_point;
 
 /**

+ 92 - 3
components/wpa_supplicant/src/rsn_supp/wpa.c

@@ -650,6 +650,8 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
     struct wpa_eapol_ie_parse ie;
     struct wpa_ptk *ptk;
     int res;
+    u8 *kde, *kde_buf = NULL;
+    size_t kde_len;
 
     wpa_sm_set_state(WPA_FIRST_HALF_4WAY_HANDSHAKE);
 
@@ -705,16 +707,30 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
     sm->tptk_set = 1;
     sm->ptk_set = 0;
     sm->key_install = true;
+    kde = sm->assoc_wpa_ie;
+    kde_len = sm->assoc_wpa_ie_len;
+    kde_buf = os_malloc(kde_len +
+                sm->assoc_rsnxe_len);
+    if (!kde_buf)
+        goto failed;
+    os_memcpy(kde_buf, kde, kde_len);
+    kde = kde_buf;
+
+    if (sm->assoc_rsnxe && sm->assoc_rsnxe_len) {
+        os_memcpy(kde + kde_len, sm->assoc_rsnxe, sm->assoc_rsnxe_len);
+        kde_len += sm->assoc_rsnxe_len;
+    }
 
     if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
-                       sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,
-                       ptk))
+                       kde, kde_len, ptk))
         goto failed;
 
+    os_free(kde_buf);
     memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
     return;
 
 failed:
+    os_free(kde_buf);
     wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
 }
 
@@ -1104,6 +1120,22 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
         return -1;
     }
 
+    if (sm->proto == WPA_PROTO_RSN &&
+        ((sm->ap_rsnxe && !ie->rsnxe) ||
+         (!sm->ap_rsnxe && ie->rsnxe) ||
+         (sm->ap_rsnxe && ie->rsnxe &&
+          (sm->ap_rsnxe_len != ie->rsnxe_len ||
+           os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0)))) {
+        wpa_printf(MSG_INFO,
+            "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
+        wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp",
+                sm->ap_rsnxe, sm->ap_rsnxe_len);
+        wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
+                ie->rsnxe, ie->rsnxe_len);
+        wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
+        return -1;
+    }
+
     return 0;
 }
 
@@ -2209,6 +2241,8 @@ void wpa_sm_deinit(void)
 {
     struct wpa_sm *sm = &gWpaSm;
     pmksa_cache_deinit(sm->pmksa);
+    os_free(sm->ap_rsnxe);
+    os_free(sm->assoc_rsnxe);
 }
 
 
@@ -2263,6 +2297,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
     int res = 0;
     struct wpa_sm *sm = &gWpaSm;
     bool use_pmk_cache = true;
+    u8 assoc_rsnxe[20];
+    size_t assoc_rsnxe_len = sizeof(assoc_rsnxe);
 
     /* Incase AP has changed it's SSID, don't try with PMK caching for SAE connection */
     /* Ideally we should use network_ctx for this purpose however currently network profile block
@@ -2357,7 +2393,14 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
     if (res < 0)
         return -1;
     sm->assoc_wpa_ie_len = res;
-    esp_set_assoc_ie((uint8_t *)bssid, NULL, 0, true);
+    res = wpa_gen_rsnxe(sm ,assoc_rsnxe, assoc_rsnxe_len);
+    if (res < 0)
+        return -1;
+    assoc_rsnxe_len = res;
+    res = wpa_sm_set_assoc_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len);
+    if (res < 0)
+        return -1;
+    esp_set_assoc_ie((uint8_t *)bssid, assoc_rsnxe, assoc_rsnxe_len, true);
     os_memset(sm->ssid, 0, sizeof(sm->ssid));
     os_memcpy(sm->ssid, ssid, ssid_len);
     sm->ssid_len = ssid_len;
@@ -2611,6 +2654,52 @@ struct wpa_sm * get_wpa_sm(void)
     return &gWpaSm;
 }
 
+int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len)
+{
+    struct wpa_sm *sm = &gWpaSm;
+    if (!sm)
+        return -1;
+
+    os_free(sm->ap_rsnxe);
+    if (!ie || len == 0) {
+        wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
+        sm->ap_rsnxe = NULL;
+        sm->ap_rsnxe_len = 0;
+    } else {
+        wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
+        sm->ap_rsnxe = os_memdup(ie, len);
+        if (!sm->ap_rsnxe)
+            return -1;
+
+        sm->ap_rsnxe_len = len;
+    }
+
+    sm->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal();
+    return 0;
+}
+
+
+int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
+{
+    if (!sm)
+        return -1;
+
+    os_free(sm->assoc_rsnxe);
+    if (!ie || len == 0) {
+        sm->assoc_rsnxe = NULL;
+        sm->assoc_rsnxe_len = 0;
+    } else {
+        wpa_hexdump(MSG_DEBUG, "RSN: set own RSNXE", ie, len);
+        sm->assoc_rsnxe = os_memdup(ie, len);
+        if (!sm->assoc_rsnxe)
+            return -1;
+
+        sm->assoc_rsnxe_len = len;
+    }
+
+    return 0;
+}
+
 #ifdef CONFIG_OWE_STA
 struct wpabuf *owe_build_assoc_req(struct wpa_sm *sm, u16 group)
 {

+ 4 - 0
components/wpa_supplicant/src/rsn_supp/wpa.h

@@ -54,6 +54,10 @@ int wpa_sm_set_key(struct install_key *sm, enum wpa_alg alg,
         u8 *key, size_t key_len,
         enum key_flag key_flag);
 
+int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len);
+
+int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
+
 #ifdef CONFIG_IEEE80211R
 
 int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len);

+ 5 - 2
components/wpa_supplicant/src/rsn_supp/wpa_i.h

@@ -48,11 +48,14 @@ struct wpa_sm {
     void *network_ctx;
 
     int rsn_enabled; /* Whether RSN is enabled in configuration */
+    int sae_pwe; /* SAE PWE generation options */
 
     int countermeasures; /*TKIP countermeasures state flag, 1:in countermeasures state*/
 
     u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
     size_t assoc_wpa_ie_len;
+    u8 *assoc_rsnxe; /* Own RSNXE from (Re)AssocReq */
+    size_t assoc_rsnxe_len;
 
     u8 eapol_version;
 
@@ -64,8 +67,8 @@ struct wpa_sm {
     unsigned int proto;
     enum wpa_states wpa_state;
 
-    u8 *ap_wpa_ie, *ap_rsn_ie;
-    size_t ap_wpa_ie_len, ap_rsn_ie_len;
+    u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
+    size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
 
     bool key_install;
 

+ 35 - 0
components/wpa_supplicant/src/rsn_supp/wpa_ie.c

@@ -35,6 +35,8 @@ int  wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
 {
     if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) {
         return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+    } else if (wpa_ie_len >=1 && wpa_ie[0] == WLAN_EID_RSNX){
+        return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
     } else if (wpa_ie[0] == WLAN_EID_WAPI) {
         return 0;
     }
@@ -293,6 +295,34 @@ int  wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
 }
 
 
+int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
+{
+    u8 *pos = rsnxe;
+    u16 capab = 0;
+    size_t flen;
+
+    if (wpa_key_mgmt_sae(sm->key_mgmt) &&
+        (sm->sae_pwe == 1 || sm->sae_pwe == 2)) {
+        capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+    }
+
+    flen = (capab & 0xff00) ? 2 : 1;
+    if (!capab)
+        return 0; /* no supported extended RSN capabilities */
+    if (rsnxe_len < 2 + flen)
+        return -1;
+    capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
+
+    *pos++ = WLAN_EID_RSNX;
+    *pos++ = flen;
+    *pos++ = capab & 0x00ff;
+    capab >>= 8;
+    if (capab)
+        *pos++ = capab;
+
+    return pos - rsnxe;
+}
+
 /**
  * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
  * @pos: Pointer to the IE header
@@ -393,6 +423,11 @@ int  wpa_supplicant_parse_ies(const u8 *buf, size_t len,
 			ie->rsn_ie_len = pos[1] + 2;
 			wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
 				    ie->rsn_ie, ie->rsn_ie_len);
+		} else if (*pos == WLAN_EID_RSNX) {
+			ie->rsnxe = pos;
+			ie->rsnxe_len = pos[1] + 2;
+			wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
+			ie->rsnxe, ie->rsnxe_len);
 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
 			ret = wpa_parse_generic(pos, end, ie);
 			if (ret < 0)

+ 3 - 1
components/wpa_supplicant/src/rsn_supp/wpa_ie.h

@@ -37,12 +37,14 @@ struct wpa_eapol_ie_parse {
 	const u8 *reassoc_deadline;
 	const u8 *key_lifetime;
 #endif /* CONFIG_IEEE80211R */
+	const u8 *rsnxe;
+	size_t rsnxe_len;
 };
 
 int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
 			     struct wpa_eapol_ie_parse *ie);
 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len);
-
+int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len);
 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
              struct wpa_ie_data *data);
 

+ 191 - 0
components/wpa_supplicant/src/utils/const_time.h

@@ -0,0 +1,191 @@
+/*
+ * Helper functions for constant time operations
+ * Copyright (c) 2019, The Linux Foundation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * These helper functions can be used to implement logic that needs to minimize
+ * externally visible differences in execution path by avoiding use of branches,
+ * avoiding early termination or other time differences, and forcing same memory
+ * access pattern regardless of values.
+ */
+
+#ifndef CONST_TIME_H
+#define CONST_TIME_H
+
+
+#if defined(__clang__)
+#define NO_UBSAN_UINT_OVERFLOW \
+	__attribute__((no_sanitize("unsigned-integer-overflow")))
+#else
+#define NO_UBSAN_UINT_OVERFLOW
+#endif
+
+
+/**
+ * const_time_fill_msb - Fill all bits with MSB value
+ * @val: Input value
+ * Returns: Value with all the bits set to the MSB of the input val
+ */
+static inline unsigned int const_time_fill_msb(unsigned int val)
+{
+	/* Move the MSB to LSB and multiple by -1 to fill in all bits. */
+	return (val >> (sizeof(val) * 8 - 1)) * ~0U;
+}
+
+
+/* Returns: -1 if val is zero; 0 if val is not zero */
+static inline unsigned int const_time_is_zero(unsigned int val)
+	NO_UBSAN_UINT_OVERFLOW
+{
+	/* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
+	return const_time_fill_msb(~val & (val - 1));
+}
+
+
+/* Returns: -1 if a == b; 0 if a != b */
+static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
+{
+	return const_time_is_zero(a ^ b);
+}
+
+
+/* Returns: -1 if a == b; 0 if a != b */
+static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
+{
+	return (u8) const_time_eq(a, b);
+}
+
+
+/**
+ * const_time_eq_bin - Constant time memory comparison
+ * @a: First buffer to compare
+ * @b: Second buffer to compare
+ * @len: Number of octets to compare
+ * Returns: -1 if buffers are equal, 0 if not
+ *
+ * This function is meant for comparing passwords or hash values where
+ * difference in execution time or memory access pattern could provide external
+ * observer information about the location of the difference in the memory
+ * buffers. The return value does not behave like memcmp(), i.e.,
+ * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
+ * memcmp(), the execution time of const_time_eq_bin() does not depend on the
+ * contents of the compared memory buffers, but only on the total compared
+ * length.
+ */
+static inline unsigned int const_time_eq_bin(const void *a, const void *b,
+					     size_t len)
+{
+	const u8 *aa = a;
+	const u8 *bb = b;
+	size_t i;
+	u8 res = 0;
+
+	for (i = 0; i < len; i++)
+		res |= aa[i] ^ bb[i];
+
+	return const_time_is_zero(res);
+}
+
+
+/**
+ * const_time_select - Constant time unsigned int selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline unsigned int const_time_select(unsigned int mask,
+					     unsigned int true_val,
+					     unsigned int false_val)
+{
+	return (mask & true_val) | (~mask & false_val);
+}
+
+
+/**
+ * const_time_select_int - Constant time int selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline int const_time_select_int(unsigned int mask, int true_val,
+					int false_val)
+{
+	return (int) const_time_select(mask, (unsigned int) true_val,
+				       (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_u8 - Constant time u8 selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
+{
+	return (u8) const_time_select(mask, true_val, false_val);
+}
+
+
+/**
+ * const_time_select_s8 - Constant time s8 selection
+ * @mask: 0 (false) or -1 (true) to identify which value to select
+ * @true_val: Value to select for the true case
+ * @false_val: Value to select for the false case
+ * Returns: true_val if mask == -1, false_val if mask == 0
+ */
+static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
+{
+	return (s8) const_time_select(mask, (unsigned int) true_val,
+				      (unsigned int) false_val);
+}
+
+
+/**
+ * const_time_select_bin - Constant time binary buffer selection copy
+ * @mask: 0 (false) or -1 (true) to identify which value to copy
+ * @true_val: Buffer to copy for the true case
+ * @false_val: Buffer to copy for the false case
+ * @len: Number of octets to copy
+ * @dst: Destination buffer for the copy
+ *
+ * This function copies the specified buffer into the destination buffer using
+ * operations with identical memory access pattern regardless of which buffer
+ * is being copied.
+ */
+static inline void const_time_select_bin(u8 mask, const u8 *true_val,
+					 const u8 *false_val, size_t len,
+					 u8 *dst)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
+}
+
+
+static inline int const_time_memcmp(const void *a, const void *b, size_t len)
+{
+	const u8 *aa = a;
+	const u8 *bb = b;
+	int diff, res = 0;
+	unsigned int mask;
+
+	if (len == 0)
+		return 0;
+	do {
+		len--;
+		diff = (int) aa[len] - (int) bb[len];
+		mask = const_time_is_zero((unsigned int) diff);
+		res = const_time_select_int(mask, res, diff);
+	} while (len);
+
+	return res;
+}
+
+#endif /* CONST_TIME_H */

+ 10 - 10
components/wpa_supplicant/test/test_sae.c

@@ -74,7 +74,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
 
         TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0);
 
-        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), NULL, &sae) == 0);
+        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae) == 0);
 
         buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
 
@@ -84,7 +84,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
 
         /* Parsing commit created by self will be detected as reflection attack*/
         TEST_ASSERT(sae_parse_commit(&sae,
-                    wpabuf_mhead(buf), buf->used, NULL, 0, default_groups) == SAE_SILENTLY_DISCARD);
+                    wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD);
 
         wpabuf_free2(buf);
         sae_clear_temp_data(&sae);
@@ -112,10 +112,10 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
         TEST_ASSERT(sae_set_group(&sae2, IANA_SECP256R1) == 0);
 
         /* STA1 prepares for commit*/
-        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), NULL, &sae1) == 0);
+        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae1) == 0);
 
         /* STA2 prepares for commit*/
-        TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd, strlen((const char *)pwd), NULL, &sae2) == 0);
+        TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd, strlen((const char *)pwd), &sae2) == 0);
 
         /* STA1 creates commit msg buffer*/
         buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
@@ -135,11 +135,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
 
         /* STA1 parses STA2 commit*/
         TEST_ASSERT(sae_parse_commit(&sae1,
-                    wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0);
+                    wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0);
 
         /* STA2 parses STA1 commit*/
         TEST_ASSERT(sae_parse_commit(&sae2,
-                    wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0);
+                    wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0);
 
         /* STA1 processes commit*/
         TEST_ASSERT(sae_process_commit(&sae1) == 0);
@@ -200,10 +200,10 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
         TEST_ASSERT(sae_set_group(&sae2, IANA_SECP256R1) == 0);
 
         /* STA1 prepares for commit*/
-        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd1), NULL, &sae1) == 0);
+        TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd1), &sae1) == 0);
 
         /* STA2 prepares for commit*/
-        TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), NULL, &sae2) == 0);
+        TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), &sae2) == 0);
 
         /* STA1 creates commit msg buffer*/
         buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
@@ -220,11 +220,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
 
         /* STA1 parses STA2 commit*/
         TEST_ASSERT(sae_parse_commit(&sae1,
-                    wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0);
+                    wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0);
 
         /* STA2 parses STA1 commit*/
         TEST_ASSERT(sae_parse_commit(&sae2,
-                    wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0);
+                    wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0);
 
         /* STA1 processes commit*/
         TEST_ASSERT(sae_process_commit(&sae1) == 0);

+ 1 - 0
examples/wifi/getting_started/station/main/station_example_main.c

@@ -115,6 +115,7 @@ void wifi_init_sta(void)
              * However these modes are deprecated and not advisable to be used. Incase your Access point
              * doesn't support WPA2, these mode can be enabled by commenting below line */
 	     .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
+	     .sae_pwe_h2e = 2,
         },
     };
     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -1500,7 +1500,6 @@ components/wifi_provisioning/src/wifi_config.c
 components/wifi_provisioning/src/wifi_provisioning_priv.h
 components/wifi_provisioning/src/wifi_scan.c
 components/wpa_supplicant/esp_supplicant/src/esp_scan_i.h
-components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c
 components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h
 components/wpa_supplicant/esp_supplicant/src/esp_wpa_err.h
 components/wpa_supplicant/include/utils/wpa_debug.h

Некоторые файлы не были показаны из-за большого количества измененных файлов