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
This commit is contained in:
parent
ebd35a1657
commit
30d6220394
16 changed files with 110 additions and 46 deletions
|
@ -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 @@
|
|||
Subproject commit d8ef004051617b225e2b2565e5323cbdd7ccb6c4
|
||||
Subproject commit eb2c39617f72257f4d4428e60151ac4a9a4d7ab1
|
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -2113,8 +2116,9 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
|
|||
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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue