Przeglądaj źródła

esp_wifi: Support for additional WPA3 testcases

1. Anti-Clogging Token Request support
2. Return correct status from SAE modules for invalid scenarios
3. Add PMK Caching support for WPA3
Nachiket Kukade 6 lat temu
rodzic
commit
00f0cdcc92

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

@@ -85,6 +85,8 @@ typedef enum {
     WIFI_REASON_802_1X_AUTH_FAILED       = 23,
     WIFI_REASON_CIPHER_SUITE_REJECTED    = 24,
 
+    WIFI_REASON_INVALID_PMKID            = 53,
+
     WIFI_REASON_BEACON_TIMEOUT           = 200,
     WIFI_REASON_NO_AP_FOUND              = 201,
     WIFI_REASON_AUTH_FAIL                = 202,

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 7df324fc40a1de5f981e4a38d8941d4c82d9a62a
+Subproject commit c47f210ea59a820f2b03706b9c9632b8d8e01757

+ 1 - 1
components/esp_wifi/src/wifi_default.c

@@ -365,4 +365,4 @@ esp_err_t esp_netif_create_default_wifi_mesh_netifs(esp_netif_t **p_netif_sta, e
         *p_netif_ap = netif_ap;
     }
     return ESP_OK;
-}
+}

+ 1 - 1
components/wpa_supplicant/include/esp_supplicant/esp_wpa.h

@@ -19,6 +19,7 @@
 #include <stdbool.h>
 #include "esp_err.h"
 #include "esp_wifi_crypto_types.h"
+#include "esp_wifi_types.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -63,7 +64,6 @@ esp_err_t esp_supplicant_init(void);
   */
 esp_err_t esp_supplicant_deinit(void);
 
-
 /**
   * @}
   */

+ 0 - 1
components/wpa_supplicant/src/common/defs.h

@@ -50,7 +50,6 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
 			 WPA_KEY_MGMT_FT_IEEE8021X |
 			 WPA_KEY_MGMT_CCKM |
 			 WPA_KEY_MGMT_OSEN |
-			 WPA_KEY_MGMT_SAE |
 			 WPA_KEY_MGMT_IEEE8021X_SHA256 |
 			 WPA_KEY_MGMT_IEEE8021X_SUITE_B |
 			 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));

+ 0 - 1
components/wpa_supplicant/src/common/sae.c

@@ -110,7 +110,6 @@ void sae_clear_temp_data(struct sae_data *sae)
 	crypto_ec_point_deinit(tmp->pwe_ecc, 1);
 	crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
 	crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
-	wpabuf_free(tmp->anti_clogging_token);
 	os_free(tmp->pw_id);
 	bin_clear_free(tmp, sizeof(*tmp));
 	sae->tmp = NULL;

+ 0 - 1
components/wpa_supplicant/src/common/sae.h

@@ -44,7 +44,6 @@ struct sae_temporary_data {
 	const struct crypto_bignum *order;
 	struct crypto_bignum *prime_buf;
 	struct crypto_bignum *order_buf;
-	struct wpabuf *anti_clogging_token;
 	char *pw_id;
 };
 

+ 2 - 1
components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h

@@ -110,6 +110,7 @@ struct wpa_funcs {
     bool (*wpa_sta_init)(void);
     bool (*wpa_sta_deinit)(void);
     void (*wpa_sta_connect)(uint8_t *bssid);
+    void (*wpa_sta_disconnected_cb)(uint8_t reason_code);
     int (*wpa_sta_rx_eapol)(u8 *src_addr, u8 *buf, u32 len);
     bool (*wpa_sta_in_4way_handshake)(void);
     void *(*wpa_ap_init)(void);
@@ -123,7 +124,7 @@ struct wpa_funcs {
     int (*wpa_config_bss)(u8 *bssid);
     int (*wpa_michael_mic_failure)(u16 is_unicast);
     uint8_t *(*wpa3_build_sae_msg)(uint8_t *bssid, uint32_t type, size_t *len);
-    int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type);
+    int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
 };
 
 struct wpa2_funcs {

+ 1 - 1
components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c

@@ -651,7 +651,7 @@ static int eap_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len, uint8_t *bss
         break;
     case EAP_CODE_SUCCESS:
         if (sm->eapKeyData) {
-            wpa_set_pmk(sm->eapKeyData);
+            wpa_set_pmk(sm->eapKeyData, NULL, false);
             os_free(sm->eapKeyData);
             sm->eapKeyData = NULL;
             wpa_printf(MSG_INFO, ">>>>>wpa2 FINISH\n");

+ 38 - 11
components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c

@@ -15,21 +15,33 @@
 #ifdef CONFIG_WPA3_SAE
 
 #include "common/sae.h"
+#include "common/ieee802_11_defs.h"
 #include "esp_wifi_driver.h"
 #include "rsn_supp/wpa.h"
 
 static struct sae_data g_sae_data;
-
+static struct wpabuf *g_sae_token = NULL;
 int g_allowed_groups[] = { IANA_SECP256R1, 0 };
 
 static struct wpabuf *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;
-	memset(&g_sae_data, 0, sizeof(g_sae_data));
 
+    if (wpa_sta_is_cur_pmksa_set()) {
+		wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
+        return NULL;
+    }
+
+	if (g_sae_token) {
+		len = wpabuf_len(g_sae_token);
+		goto reuse_data;
+	}
+
+	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;
@@ -47,17 +59,24 @@ static struct wpabuf *wpa3_build_sae_commit(u8 *bssid)
 		return NULL;
 	}
 
-	buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
+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, NULL, NULL) != ESP_OK) {
+	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;
@@ -104,11 +123,12 @@ static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, u32 *sae_msg_len)
 	if (buf) {
 		*sae_msg_len = (u32)wpabuf_len(buf);
 		return wpabuf_mhead_u8(buf);
-	} else
+	} else {
 		return NULL;
+    }
 }
 
-static int wpa3_parse_sae_commit(u8 *buf, u32 len)
+static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
 {
 	int ret;
 
@@ -118,16 +138,23 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len)
 		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 ESP_FAIL;
+		return ret;
 	}
 
 	ret = sae_process_commit(&g_sae_data);
 	if (ret) {
 		wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
-		return ESP_FAIL;
+		return ret;
 	}
 
 	return ESP_OK;
@@ -147,19 +174,19 @@ static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
 	}
 	g_sae_data.state = SAE_ACCEPTED;
 
-	wpa_set_pmk(g_sae_data.pmk);
+	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)
+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);
+			ret = wpa3_parse_sae_commit(buf, len, status);
 			break;
 		case SAE_MSG_CONFIRM:
 			ret = wpa3_parse_sae_confirm(buf, len);

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

@@ -176,6 +176,25 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t
     return ret;
 }
 
+static void wpa_sta_disconnected_cb(uint8_t reason_code)
+{
+    switch (reason_code) {
+        case WIFI_REASON_UNSPECIFIED:
+        case WIFI_REASON_AUTH_EXPIRE:
+        case WIFI_REASON_NOT_AUTHED:
+        case WIFI_REASON_NOT_ASSOCED:
+        case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
+        case WIFI_REASON_INVALID_PMKID:
+        case WIFI_REASON_AUTH_FAIL:
+        case WIFI_REASON_ASSOC_FAIL:
+        case WIFI_REASON_CONNECTION_FAIL:
+            wpa_sta_clear_curr_pmksa();
+            break;
+        default:
+            break;
+    }
+}
+
 int esp_supplicant_init(void)
 {
     struct wpa_funcs *wpa_cb;
@@ -189,6 +208,7 @@ int esp_supplicant_init(void)
     wpa_cb->wpa_sta_deinit     = wpa_deattach;
     wpa_cb->wpa_sta_rx_eapol   = wpa_sm_rx_eapol;
     wpa_cb->wpa_sta_connect    = wpa_sta_connect;
+    wpa_cb->wpa_sta_disconnected_cb = wpa_sta_disconnected_cb;
     wpa_cb->wpa_sta_in_4way_handshake = wpa_sta_in_4way_handshake;
 
     wpa_cb->wpa_ap_join       = wpa_ap_join;

+ 8 - 5
components/wpa_supplicant/src/rsn_supp/pmksa_cache.c

@@ -103,7 +103,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
  */
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-        const u8 *kck, size_t kck_len,
+        const u8 *pmkid, const u8 *kck, size_t kck_len,
         const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
 {
     struct rsn_pmksa_cache_entry *entry, *pos, *prev;
@@ -120,8 +120,11 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
         return NULL;
     os_memcpy(entry->pmk, pmk, pmk_len);
     entry->pmk_len = pmk_len;
-    rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
-            wpa_key_mgmt_sha256(akmp));
+    if (pmkid)
+        os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
+    else
+        rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
+                  wpa_key_mgmt_sha256(akmp));
     entry->expiration = now_sec + dot11RSNAConfigPMKLifetime;
     entry->reauth_time = now_sec + dot11RSNAConfigPMKLifetime *
         dot11RSNAConfigPMKReauthThreshold / 100;
@@ -318,7 +321,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
     struct rsn_pmksa_cache_entry *new_entry;
 
     new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
-            NULL, 0,
+            NULL, NULL, 0,
             aa, pmksa->sm->own_addr,
             old_entry->network_ctx, old_entry->akmp);
     if (new_entry == NULL)
@@ -428,7 +431,7 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
                 network_ctx,
                 bssid);
     if (sm->cur_pmksa) {
-        wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
+        wpa_hexdump(MSG_ERROR, "RSN: PMKSA cache entry found - PMKID",
                 sm->cur_pmksa->pmkid, PMKID_LEN);
         return 0;
     }

+ 2 - 2
components/wpa_supplicant/src/rsn_supp/pmksa_cache.h

@@ -57,7 +57,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-        const u8 *kck, size_t kck_len,
+        const u8 *pmkid, const u8 *kck, size_t kck_len,
         const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
 struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
 void pmksa_cache_clear_current(struct wpa_sm *sm);
@@ -105,7 +105,7 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
 
     static inline struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-        const u8 *kck, size_t kck_len,
+        const u8 *pmkid, const u8 *kck, size_t kck_len,
         const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
 {
     return NULL;

+ 29 - 17
components/wpa_supplicant/src/rsn_supp/wpa.c

@@ -399,12 +399,9 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
             if (sm->proto == WPA_PROTO_RSN &&
                     !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
                     !wpa_key_mgmt_ft(sm->key_mgmt)) {
-                sa = pmksa_cache_add(sm->pmksa,
-                        sm->pmk, pmk_len,
-                        NULL, 0,
-						     src_addr, sm->own_addr,
-						     sm->network_ctx,
-						     sm->key_mgmt);
+                sa = pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len,
+                                     NULL, NULL, 0, src_addr, sm->own_addr,
+                                     sm->network_ctx, sm->key_mgmt);
 			}
 			if (!sm->cur_pmksa && pmkid &&
 			    pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
@@ -590,8 +587,8 @@ void   wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
     if (res)
         goto failed;
 
-    if (esp_wifi_sta_prof_is_wpa2_internal() 
-            && esp_wifi_sta_get_prof_authmode_internal() == WPA2_AUTH_ENT) {
+    if (esp_wifi_sta_prof_is_wpa2_internal() &&
+        esp_wifi_sta_get_prof_authmode_internal() == WPA2_AUTH_ENT) {
         pmksa_cache_set_current(sm, NULL, sm->bssid, 0, 0);
     }
 
@@ -1991,7 +1988,7 @@ void wpa_sm_set_state(enum wpa_states state)
  * Configure the PMK for WPA state machine.
  */
 void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
-		    const u8 *bssid)
+                    const u8 *pmkid, const u8 *bssid)
 {
 	if (sm == NULL)
 		return;
@@ -2006,9 +2003,9 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
 #endif /* CONFIG_IEEE80211R */
 
 	if (bssid) {
-		pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0,
-				bssid, sm->own_addr,
-				sm->network_ctx, sm->key_mgmt);
+		pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
+                        bssid, sm->own_addr,
+                        sm->network_ctx, sm->key_mgmt);
 	}
 }
 
@@ -2090,12 +2087,18 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
     }
 }
 
-void wpa_set_pmk(uint8_t *pmk)
+void wpa_set_pmk(uint8_t *pmk, const u8 *pmkid, bool cache_pmksa)
 {
     struct wpa_sm *sm = &gWpaSm;
     
     memcpy(sm->pmk, pmk, PMK_LEN);
     sm->pmk_len = PMK_LEN;
+
+    if (cache_pmksa) {
+        pmksa_cache_add(sm->pmksa, pmk, PMK_LEN, pmkid, NULL, 0,
+                        sm->bssid, sm->own_addr,
+                        sm->network_ctx, sm->key_mgmt);
+    }
 }
 
 int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len)
@@ -2112,9 +2115,10 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
     memcpy(sm->own_addr, macddr, ETH_ALEN);
     memcpy(sm->bssid, bssid, ETH_ALEN);
     sm->ap_notify_completed_rsne = esp_wifi_sta_is_ap_notify_completed_rsne_internal();
-        
-    if (esp_wifi_sta_prof_is_wpa2_internal() 
-            && esp_wifi_sta_get_prof_authmode_internal() == WPA2_AUTH_ENT) {
+
+    if (sm->key_mgmt == WPA_KEY_MGMT_SAE ||
+        (esp_wifi_sta_prof_is_wpa2_internal() &&
+         esp_wifi_sta_get_prof_authmode_internal() == WPA2_AUTH_ENT)) {
         pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, 0);
         wpa_sm_set_pmk_from_pmksa(sm);
     }
@@ -2153,7 +2157,7 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
      *    PMK.
      */
     if (sm->key_mgmt == WPA_KEY_MGMT_SAE)
-	return;
+        return;
 
     /* This is really SLOW, so just re cacl while reset param */
     if (esp_wifi_sta_get_reset_param_internal() != 0) {
@@ -2358,5 +2362,13 @@ bool wpa_sta_is_cur_pmksa_set(void) {
     return (pmksa_cache_get_current(sm) != NULL);
 }
 
+void wpa_sta_clear_curr_pmksa(void) {
+    struct wpa_sm *sm = &gWpaSm;
+
+    if (sm->pmksa)
+        pmksa_cache_flush(sm->pmksa, NULL, sm->pmk, sm->pmk_len);
+    pmksa_cache_clear_current(sm);
+}
+
 #endif // ESP_SUPPLICANT
 

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

@@ -119,7 +119,7 @@ void wpa_sm_set_state(enum wpa_states state);
 
 char * dup_binstr(const void *src, size_t len);
 
-void wpa_set_pmk(uint8_t *pmk);
+void wpa_set_pmk(uint8_t *pmk, const u8 *pmkid, bool cache_pmksa);
 
 int wpa_hook_init(void);
 
@@ -133,5 +133,7 @@ wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher);
 
 uint32_t cipher_type_map_supp_to_public(wifi_cipher_type_t cipher);
 
+void wpa_sta_clear_curr_pmksa(void);
+
 #endif /* WPA_H */
 

+ 2 - 2
components/wpa_supplicant/src/rsn_supp/wpa_ie.c

@@ -220,9 +220,9 @@ static int  wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
 #ifdef CONFIG_IEEE80211W
     if (sm->pmf_cfg.capable) {
         capab |= WPA_CAPABILITY_MFPC;
-        if (sm->pmf_cfg.required) {
+        if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE) {
             capab |= WPA_CAPABILITY_MFPR;
-	}
+        }
     }
 #endif /* CONFIG_IEEE80211W */
     WPA_PUT_LE16(pos, capab);