Add support for PMF configuration and negotiation

1. Add APIs for configuring PMF through set config.
2. Map Supplicant and Wifi Cipher types.
3. Add support for PMF negotiation while generating RSN IE.
This commit is contained in:
Nachiket Kukade 2020-04-30 18:47:02 +05:30
parent b7dc47108f
commit 1b7f3fee5c
10 changed files with 122 additions and 46 deletions

View file

@ -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.

View file

@ -106,4 +106,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
CONFIG_ECC
CONFIG_TLSV12
CONFIG_SHA256
CONFIG_IEEE80211W
)

View file

@ -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

View file

@ -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
*/

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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)

View file

@ -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 */

View file

@ -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;
};
/**

View file

@ -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;