diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index 6d6f9c8e1..73df72faf 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/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, diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index d8ef00405..eb2c39617 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit d8ef004051617b225e2b2565e5323cbdd7ccb6c4 +Subproject commit eb2c39617f72257f4d4428e60151ac4a9a4d7ab1 diff --git a/components/esp_wifi/src/wifi_default.c b/components/esp_wifi/src/wifi_default.c index 7fb4b9114..7e0e41afa 100644 --- a/components/esp_wifi/src/wifi_default.c +++ b/components/esp_wifi/src/wifi_default.c @@ -388,4 +388,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; -} \ No newline at end of file +} diff --git a/components/wpa_supplicant/include/esp_supplicant/esp_wpa.h b/components/wpa_supplicant/include/esp_supplicant/esp_wpa.h index a268d9a46..202c907d6 100644 --- a/components/wpa_supplicant/include/esp_supplicant/esp_wpa.h +++ b/components/wpa_supplicant/include/esp_supplicant/esp_wpa.h @@ -19,6 +19,7 @@ #include #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); - /** * @} */ diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index ec4e69ab0..4906ff612 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/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)); diff --git a/components/wpa_supplicant/src/common/sae.c b/components/wpa_supplicant/src/common/sae.c index 66f5f3fed..29a41c456 100644 --- a/components/wpa_supplicant/src/common/sae.c +++ b/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; diff --git a/components/wpa_supplicant/src/common/sae.h b/components/wpa_supplicant/src/common/sae.h index 6c99a73ce..24437c0d0 100644 --- a/components/wpa_supplicant/src/common/sae.h +++ b/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; }; diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h b/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h index 6be9a747d..9999251e2 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h +++ b/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 { diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c index cb1142621..7d0ab8cd1 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c @@ -653,7 +653,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"); diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c index 014cabb0d..cdafaf3ab 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c +++ b/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); diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c index 95e6c6c96..bbb40e9aa 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c +++ b/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; diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c index 0f42eb404..b8ea823d3 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c +++ b/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; } diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h index 6e314385c..e2c9156a5 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h +++ b/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; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 4e62ac454..7e66dc952 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/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 diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 68c2b3e53..dc594b03d 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/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 */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 9aaf3bc4a..d648a4542 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/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);