diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index 0f9d9643ea..a07cfde080 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/components/esp_wifi/include/esp_wifi_types.h @@ -134,6 +134,7 @@ typedef enum { WIFI_CIPHER_TYPE_TKIP, /**< the cipher type is TKIP */ WIFI_CIPHER_TYPE_CCMP, /**< the cipher type is CCMP */ WIFI_CIPHER_TYPE_TKIP_CCMP, /**< the cipher type is TKIP and CCMP */ + WIFI_CIPHER_TYPE_AES_CMAC128,/**< the cipher type is AES-CMAC-128 */ WIFI_CIPHER_TYPE_UNKNOWN, /**< the cipher type is unknown */ } wifi_cipher_type_t; @@ -199,6 +200,12 @@ typedef enum { WIFI_BW_HT40, /* Bandwidth is HT40 */ } wifi_bandwidth_t; +/** Configuration structure for Protected Management Frame */ +typedef struct { + bool capable; /**< Advertizes support for Protected Management Frame. Device will prefer to connect in PMF mode if other device also advertizes PMF capability. */ + bool required; /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */ +} wifi_pmf_config_t; + /** @brief Soft-AP configuration settings for the ESP32 */ typedef struct { uint8_t ssid[32]; /**< SSID of ESP32 soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */ @@ -222,6 +229,7 @@ typedef struct { uint16_t listen_interval; /**< Listen interval for ESP32 station to receive beacon when WIFI_PS_MAX_MODEM is set. Units: AP beacon intervals. Defaults to 3 if set to 0. */ wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */ wifi_scan_threshold_t threshold; /**< When sort_method is set, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */ + wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */ } wifi_sta_config_t; /** @brief Configuration data for ESP32 AP or STA. diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 36dd7a096b..b7764b48b3 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -106,4 +106,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_ECC CONFIG_TLSV12 CONFIG_SHA256 + CONFIG_IEEE80211W ) diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index e85e9979fb..8553cedc87 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -2,4 +2,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant COMPONENT_PRIV_INCLUDEDIRS := src COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps -CFLAGS += -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing +CFLAGS += -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index 2f4360ba98..f2fd1f6172 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -22,7 +22,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_CIPHER_WEP104 BIT(8) #define WPA_CIPHER_TKIP BIT(1) #define WPA_CIPHER_CCMP BIT(3) -#define WPA_CIPHER_AES_128_CMAC BIT(2) +#define WPA_CIPHER_AES_128_CMAC BIT(5) #define WPA_CIPHER_GCMP BIT(6) #define WPA_KEY_MGMT_IEEE8021X BIT(0) @@ -304,7 +304,6 @@ enum wpa_states { #define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 #define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 - /** * enum mfp_options - Management frame protection (IEEE 802.11w) options */ 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 b4767ef197..08d1efdfb4 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wifi_driver.h @@ -63,7 +63,8 @@ enum { WPA2_AUTH_PSK = 0x05, WPA_AUTH_CCKM = 0x06, WPA2_AUTH_CCKM = 0x07, - WPA2_AUTH_INVALID = 0x08, + WPA2_AUTH_PSK_SHA256= 0x08, + WPA2_AUTH_INVALID = 0x09, }; typedef enum { @@ -218,5 +219,7 @@ esp_err_t esp_wifi_internal_supplicant_header_md5_check(const char *md5); int esp_wifi_sta_update_ap_info_internal(void); uint8_t *esp_wifi_sta_get_ap_info_prof_pmk_internal(void); esp_err_t esp_wifi_set_wps_start_flag_internal(bool start); +uint16_t esp_wifi_sta_pmf_enabled(void); +wifi_cipher_type_t esp_wifi_sta_get_mgmt_group_cipher(void); #endif /* _ESP_WIFI_DRIVER_H_ */ 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 af6ef8ae3b..434b666b48 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c @@ -158,32 +158,6 @@ void wpa_sta_connect(uint8_t *bssid) WPA_ASSERT(ret == 0); } -int cipher_type_map(int wpa_cipher) -{ - switch (wpa_cipher) { - case WPA_CIPHER_NONE: - return WIFI_CIPHER_TYPE_NONE; - - case WPA_CIPHER_WEP40: - return WIFI_CIPHER_TYPE_WEP40; - - case WPA_CIPHER_WEP104: - return WIFI_CIPHER_TYPE_WEP104; - - case WPA_CIPHER_TKIP: - return WIFI_CIPHER_TYPE_TKIP; - - case WPA_CIPHER_CCMP: - return WIFI_CIPHER_TYPE_CCMP; - - case WPA_CIPHER_CCMP|WPA_CIPHER_TKIP: - return WIFI_CIPHER_TYPE_TKIP_CCMP; - - default: - return WIFI_CIPHER_TYPE_UNKNOWN; - } -} - int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data) { struct wpa_ie_data ie; @@ -191,12 +165,12 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie); data->proto = ie.proto; - data->pairwise_cipher = cipher_type_map(ie.pairwise_cipher); - data->group_cipher = cipher_type_map(ie.group_cipher); + data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher); + data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher); data->key_mgmt = ie.key_mgmt; data->capabilities = ie.capabilities; data->pmkid = ie.pmkid; - data->mgmt_group_cipher = cipher_type_map(ie.mgmt_group_cipher); + data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher); return ret; } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index cb9220fb74..ec8406e1c2 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -46,7 +46,7 @@ /* fix buf for tx for now */ #define WPA_TX_MSG_BUFF_MAXLEN 200 -#define ASSOC_IE_LEN 24 + 2 + PMKID_LEN +#define ASSOC_IE_LEN 24 + 2 + PMKID_LEN + RSN_SELECTOR_LEN u8 assoc_ie_buf[ASSOC_IE_LEN+2]; void set_assoc_ie(u8 * assoc_buf); @@ -76,6 +76,65 @@ void eapol_sm_notify_eap_success(Boolean success) { } + +wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher) +{ + switch (wpa_cipher) { + case WPA_CIPHER_NONE: + return WIFI_CIPHER_TYPE_NONE; + + case WPA_CIPHER_WEP40: + return WIFI_CIPHER_TYPE_WEP40; + + case WPA_CIPHER_WEP104: + return WIFI_CIPHER_TYPE_WEP104; + + case WPA_CIPHER_TKIP: + return WIFI_CIPHER_TYPE_TKIP; + + case WPA_CIPHER_CCMP: + return WIFI_CIPHER_TYPE_CCMP; + + case WPA_CIPHER_CCMP|WPA_CIPHER_TKIP: + return WIFI_CIPHER_TYPE_TKIP_CCMP; + + case WPA_CIPHER_AES_128_CMAC: + return WIFI_CIPHER_TYPE_AES_CMAC128; + + default: + return WIFI_CIPHER_TYPE_UNKNOWN; + } +} + +uint32_t cipher_type_map_public_to_supp(wifi_cipher_type_t cipher) +{ + switch (cipher) { + case WIFI_CIPHER_TYPE_NONE: + return WPA_CIPHER_NONE; + + case WIFI_CIPHER_TYPE_WEP40: + return WPA_CIPHER_WEP40; + + case WIFI_CIPHER_TYPE_WEP104: + return WPA_CIPHER_WEP104; + + case WIFI_CIPHER_TYPE_TKIP: + return WPA_CIPHER_TKIP; + + case WIFI_CIPHER_TYPE_CCMP: + return WPA_CIPHER_CCMP; + + case WIFI_CIPHER_TYPE_TKIP_CCMP: + return WPA_CIPHER_CCMP|WPA_CIPHER_TKIP; + + case WIFI_CIPHER_TYPE_AES_CMAC128: + return WPA_CIPHER_AES_128_CMAC; + + default: + return WPA_CIPHER_NONE; + } +} + /** * get_bssid - Get the current BSSID * @priv: private driver interface data @@ -1169,7 +1228,7 @@ int ieee80211w_set_keys(struct wpa_sm *sm, } } - if (ieee80211w_set_keys(sm, &ie) < 0) { + if (sm->pmf_cfg.capable && ieee80211w_set_keys(sm, &ie) < 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "RSN: Failed to configure IGTK"); #endif @@ -1746,7 +1805,11 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) } key_info = WPA_GET_BE16(key->key_info); ver = key_info & WPA_KEY_INFO_TYPE_MASK; + if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && +#ifdef CONFIG_IEEE80211W + ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && +#endif ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Unsupported EAPOL-Key descriptor " @@ -1755,6 +1818,14 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) goto out; } +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->key_mgmt)) { + if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { + goto out; + } + } else +#endif + if (sm->pairwise_cipher == WPA_CIPHER_CCMP && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { #ifdef DEBUG_PRINT @@ -1977,10 +2048,13 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) struct wpa_sm *sm = &gWpaSm; sm->proto = wpa_proto; - if (auth_mode == WPA2_AUTH_ENT) + if (auth_mode == WPA2_AUTH_ENT) { sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X; /* for wpa2 enterprise */ - else + } else if (auth_mode == WPA2_AUTH_PSK) { sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */ + } else if (auth_mode == WPA2_AUTH_PSK_SHA256) { + sm->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; + } } void wpa_set_pmk(uint8_t *pmk) @@ -2011,6 +2085,17 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, 0); wpa_sm_set_pmk_from_pmksa(sm); } + +#ifdef CONFIG_IEEE80211W + if (esp_wifi_sta_pmf_enabled()) { + wifi_config_t wifi_cfg; + + esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_cfg); + sm->pmf_cfg = wifi_cfg.sta.pmf_cfg; + sm->mgmt_group_cipher = cipher_type_map_public_to_supp(esp_wifi_sta_get_mgmt_group_cipher()); + } +#endif + set_assoc_ie(assoc_ie_buf); /* use static buffer */ res = wpa_gen_wpa_ie(sm, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len); if (res < 0) diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index aa81eb1e70..81aa28b547 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -19,6 +19,7 @@ #include "utils/common.h" #include "common/defs.h" #include "common/wpa_common.h" +#include "esp_wifi_types.h" #include "esp_wifi_crypto_types.h" #include "wpa_i.h" @@ -122,5 +123,9 @@ char * dup_binstr(const void *src, size_t len); int wpa_michael_mic_failure(u16 isunicast); +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); + #endif /* WPA_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 51ce03aa2f..e0242fbcb7 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -89,6 +89,7 @@ struct wpa_sm { u16 key_info; //used for txcallback param u16 txcb_flags; bool ap_notify_completed_rsne; + wifi_pmf_config_t pmf_cfg; }; /** diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 5559392cab..77ef60c07b 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -214,10 +214,12 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, /* RSN Capabilities */ capab = 0; #ifdef CONFIG_IEEE80211W - if (sm->mfp) + if (sm->pmf_cfg.capable) { capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; + if (sm->pmf_cfg.required) { + capab |= WPA_CAPABILITY_MFPR; + } + } #endif /* CONFIG_IEEE80211W */ WPA_PUT_LE16(pos, capab); pos += 2; @@ -229,16 +231,14 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, /* PMKID */ os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN); pos += PMKID_LEN; + } else { + /* 0 PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; } #ifdef CONFIG_IEEE80211W if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - if (!sm->cur_pmksa) { - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - } - /* Management Group Cipher Suite */ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); pos += RSN_SELECTOR_LEN;