Merge branch 'feature/pmf_support_for_softAP' into 'master'

esp_wifi: Add pmf support for softAP.

Closes WIFI-1353

See merge request espressif/esp-idf!14906
pull/8396/head
Jiang Jiang Jian 2022-02-10 04:17:00 +00:00
commit cca2234619
10 zmienionych plików z 87 dodań i 44 usunięć

Wyświetl plik

@ -2000,7 +2000,6 @@ ieee80211_set_tx_pti = 0x40001e58;
wifi_is_started = 0x40001e5c;
ieee80211_gettid = 0x40001e60;
ieee80211_ccmp_decrypt = 0x40001e64;
ieee80211_ccmp_encrypt = 0x40001e68;
ccmp_encap = 0x40001e6c;
ccmp_decap = 0x40001e70;
tkip_encap = 0x40001e74;
@ -2012,8 +2011,6 @@ dbg_hmac_statis_dump = 0x40001e88;
ieee80211_send_action_vendor_spec = 0x40001e8c;
ieee80211_send_mgmt = 0x40001e90;
ieee80211_auth_construct = 0x40001e94;
ieee80211_deauth_construct = 0x40001e98;
ieee80211_disassoc_construct = 0x40001e9c;
ieee80211_vnd_lora_ie_size = 0x40001ea0;
ieee80211_vnd_ie_size = 0x40001ea4;
ieee80211_add_ssid = 0x40001ea8;
@ -2021,7 +2018,6 @@ ieee80211_add_rates = 0x40001eac;
ieee80211_add_xrates = 0x40001eb0;
ieee80211_is_ht_cipher = 0x40001eb4;
ieee80211_assoc_req_construct = 0x40001eb8;
ieee80211_assoc_resp_construct = 0x40001ebc;
ieee80211_setup_lr_rates = 0x40001ec0;
ieee80211_ht_node_init = 0x40001ec4;
ieee80211_is_support_rate = 0x40001ec8;
@ -2066,7 +2062,6 @@ ieee80211_alloc_tx_buf = 0x40001f60;
ieee80211_output_do = 0x40001f64;
ieee80211_send_nulldata = 0x40001f68;
ieee80211_setup_robust_mgmtframe = 0x40001f6c;
ieee80211_mgmt_output = 0x40001f70;
ieee80211_encap_null_data = 0x40001f74;
ieee80211_send_deauth = 0x40001f78;
ieee80211_alloc_deauth = 0x40001f7c;

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -215,7 +215,7 @@ typedef enum {
/** 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 capable; /**< Device will always 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;
@ -231,6 +231,7 @@ typedef struct {
uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */
wifi_cipher_type_t pairwise_cipher; /**< pairwise cipher of SoftAP, group cipher will be derived using this. cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */
bool ftm_responder; /**< Enable FTM Responder mode */
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */
} wifi_ap_config_t;
/** @brief STA configuration settings for the ESP32 */

@ -1 +1 @@
Subproject commit cd7d14917f2c3d0ea4382f4a188cb290304faf47
Subproject commit 66cc3ae82adce95f38d1f6738b00fca5bf09fda1

Wyświetl plik

@ -1,10 +1,9 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "utils/includes.h"
#include "utils/common.h"
@ -27,6 +26,7 @@ void *hostap_init(void)
u8 mac[6];
u16 spp_attrubute = 0;
u8 pairwise_cipher;
wifi_pmf_config_t pmf_cfg;
hapd = (struct hostapd_data *)os_zalloc(sizeof(struct hostapd_data));
@ -60,6 +60,16 @@ void *hostap_init(void)
}
pairwise_cipher = esp_wifi_ap_get_prof_pairwise_cipher_internal();
#ifdef CONFIG_IEEE80211W
esp_wifi_get_pmf_config_internal(&pmf_cfg, WIFI_IF_AP);
if (pmf_cfg.required) {
pairwise_cipher = WIFI_CIPHER_TYPE_CCMP;
}
#endif /* CONFIG_IEEE80211W */
/* TKIP is compulsory in WPA Mode */
if (auth_conf->wpa == WPA_PROTO_WPA && pairwise_cipher == WIFI_CIPHER_TYPE_CCMP) {
pairwise_cipher = WIFI_CIPHER_TYPE_TKIP_CCMP;
@ -81,6 +91,18 @@ void *hostap_init(void)
auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
auth_conf->eapol_version = EAPOL_VERSION;
#ifdef CONFIG_IEEE80211W
if (pmf_cfg.required && pmf_cfg.capable) {
auth_conf->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
wpa_printf(MSG_DEBUG, "%s :pmf required", __func__);
} else if (pmf_cfg.capable && !pmf_cfg.required) {
auth_conf->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
wpa_printf(MSG_DEBUG, "%s : pmf optional", __func__);
}
#endif /* CONFIG_IEEE80211W */
spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_AP);
auth_conf->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE);
auth_conf->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_REQ_ENABLE : SPP_AMSDU_REQ_DISABLE);

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -116,7 +116,7 @@ struct wpa_funcs {
bool (*wpa_sta_in_4way_handshake)(void);
void *(*wpa_ap_init)(void);
bool (*wpa_ap_deinit)(void *data);
bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len);
bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, bool *pmf_enable);
bool (*wpa_ap_remove)(void *sm);
uint8_t *(*wpa_ap_get_wpa_ie)(uint8_t *len);
bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len);
@ -268,5 +268,6 @@ esp_err_t esp_wifi_action_tx_req(uint8_t type, uint8_t channel,
esp_err_t esp_wifi_remain_on_channel(uint8_t ifx, uint8_t type, uint8_t channel,
uint32_t wait_time_ms, wifi_action_rx_cb_t rx_cb);
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);
#endif /* _ESP_WIFI_DRIVER_H_ */

Wyświetl plik

@ -369,7 +369,7 @@ int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len);
bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len, bool *pmf_enable);
bool wpa_ap_remove(void* sm);
#endif /* HOSTAPD_CONFIG_H */

Wyświetl plik

@ -140,7 +140,35 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
enum wpa_alg alg, const u8 *addr, int idx,
u8 *key, size_t key_len)
{
return esp_wifi_set_ap_key_internal(alg, addr, idx, key, key_len);
int ret;
if (alg == WIFI_WPA_ALG_IGTK) {
if (key) {
wpa_printf (MSG_DEBUG, "%s : igtk idx %d\n", __func__, idx);
wifi_wpa_igtk_t *igtk = malloc(sizeof(wifi_wpa_igtk_t));
if (igtk != NULL) {
memcpy(&igtk->igtk[0], key, WPA_IGTK_LEN);
memset((uint8_t*)&igtk->pn[0],0,6);
igtk->keyid[0] = idx;
igtk->keyid[1] = 0;
} else {
return -1;
}
ret = esp_wifi_set_igtk_internal(ESP_IF_WIFI_AP, igtk);
os_free(igtk);
return ret;
} else {
wpa_printf( MSG_DEBUG, "Key is empty");
return -1;
}
} else {
wpa_printf( MSG_DEBUG, "%s : key idx %d alg %d vlan_id %d key_len %d key \n", __func__, idx, alg, vlan_id, key_len);
return esp_wifi_set_ap_key_internal(alg, addr, idx, key, key_len);
}
return 0;
}
@ -157,7 +185,7 @@ static inline int
wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *data, size_t data_len, int encrypt)
{
void *buffer = os_malloc(256);
void *buffer = os_malloc(data_len + sizeof(struct l2_ethhdr));
struct l2_ethhdr *eth = buffer;
if (!buffer){
@ -2304,8 +2332,8 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
group->IGTK[group->GN_igtk - 4],
WPA_IGTK_LEN) < 0)
ret = -1;
#endif /* CONFIG_IEEE80211W */
#endif /* CONFIG_IEEE80211W */
return ret;
}
@ -2385,7 +2413,7 @@ static int wpa_sm_step(struct wpa_state_machine *sm)
return 0;
}
bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len)
bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len, bool *pmf_enable)
{
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();
struct wpa_state_machine **wpa_sm;
@ -2412,7 +2440,10 @@ bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len)
if (wpa_validate_wpa_ie(hapd->wpa_auth, *wpa_sm, wpa_ie, wpa_ie_len)) {
return false;
}
}
//Check whether AP uses Management Frame Protection for this connection
*pmf_enable = wpa_auth_uses_mfp(*wpa_sm);
}
wpa_auth_sta_associated(hapd->wpa_auth, *wpa_sm);

Wyświetl plik

@ -25,31 +25,12 @@ An attacker can use eavesdropping and packet injection to send spoofed (de)authe
PMF provides protection against these attacks by encrypting unicast management frames and providing integrity checks for broadcast management frames. These include deauthentication, disassociation and robust management frames. It also provides Secure Association (SA) teardown mechanism to prevent spoofed association/authentication frames from disconnecting already connected clients.
API & Usage
+++++++++++
There are 3 types of PMF configuration modes on both station and AP side -
- PMF Optional
- PMF Required
- PMF Disabled
:cpp:func:`esp_wifi_set_config` can be used to configure PMF mode by setting appropriate flags in `pmf_cfg` parameter. Currently, PMF is supported only in Station mode.
While setting up a Station, configure PMF using two flags ``capable`` and ``required`` like below.
.. code-block:: c
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_WIFI_SSID,
.password = EXAMPLE_WIFI_PASSWORD,
.pmf_cfg = {
.capable = true,
.required = false
}
}
};
{IDF_TARGET_NAME} supports three modes of PMF by combination of these two flags -
- PMF Optional : ``.capable = true, .required = false``
- PMF Required : ``.capable = true, .required = true``
- PMF Disabled : ``.capable = false, .required = false``
Depending on what AP side PMF Mode is, the resulting connnection will behave differently. The table below summarises all possible outcomes -
Depending on PMF configurations on Station and AP side, the resulting connection will behave differently. The table below summarises all possible outcomes -
+--------------+------------------------+---------------------------+
| STA Setting | AP Setting | Outcome |
@ -67,7 +48,14 @@ While setting up a Station, configure PMF using two flags ``capable`` and ``requ
| PMF Disabled | PMF Required | AP refuses Connection |
+--------------+------------------------+---------------------------+
PMF Optional Mode, which is shown in the example of ``wifi_confit_t``, is suggested to be used in all Station configurations. This is to take the additional security benefit of PMF whenever possible without breaking connections with legacy AP's.
API & Usage
+++++++++++
{IDF_TARGET_NAME} supports PMF in both Station and SoftAP mode. For both, the default mode is PMF Optional and disabling PMF is not possible. For even higher security, PMF required mode can be enabled by setting the ``required`` flag in `pmf_cfg` while using the :cpp:func:`esp_wifi_set_config` API. This will result in the device only connecting to a PMF enabled device and rejecting others.
.. attention::
``capable`` flag in `pmf_cfg` is deprecated and set to true internally. This is to take the additional security benefit of PMF whenever possible.
WPA3-Personal
-------------

Wyświetl plik

@ -6,6 +6,8 @@ This example shows how to use the Wi-Fi SoftAP functionality of the Wi-Fi driver
## How to use example
SoftAP supports Protected Management Frames(PMF). Necessary configurations can be set using pmf flags. Please refer [Wifi-Security](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi-security.html) for more info.
### Configure the project
Open the project configuration menu (`idf.py menuconfig`).

Wyświetl plik

@ -66,7 +66,10 @@ void wifi_init_softap(void)
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
.authmode = WIFI_AUTH_WPA_WPA2_PSK,
.pmf_cfg = {
.required = false,
},
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {