feat(wifi): Add SAE EXT key support for esp station

This commit is contained in:
Shreyas Sheth
2023-10-09 11:02:41 +05:30
parent 98cc860e86
commit ee9ce51133
11 changed files with 77 additions and 68 deletions

View File

@@ -56,7 +56,7 @@ typedef struct {
} wifi_country_t;
/* Strength of authmodes */
/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK */
/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA3_PSK = WPA2_WPA3_PSK < WPA3_EXT_PSK */
typedef enum {
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
WIFI_AUTH_WEP, /**< authenticate mode : WEP */
@@ -70,6 +70,7 @@ typedef enum {
WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */
WIFI_AUTH_OWE, /**< authenticate mode : OWE */
WIFI_AUTH_WPA3_ENT_192, /**< authenticate mode : WPA3_ENT_SUITE_B_192_BIT */
WIFI_AUTH_WPA3_EXT_PSK, /**< authenticate mode : WPA3_PSK_EXT_KEY */
WIFI_AUTH_MAX
} wifi_auth_mode_t;

View File

@@ -172,7 +172,7 @@ if(CONFIG_ESP_WIFI_ENABLE_SAE_PK)
"src/common/sae_pk.c")
endif()
if(CONFIG_ESP_WIFI_11KV_SUPPORT OR CONFIG_ESP_WIFI_11R_SUPPORT OR CONFIG_ESP_WIFI_ENABLE_SAE_PK)
if(CONFIG_ESP_WIFI_11KV_SUPPORT OR CONFIG_ESP_WIFI_11R_SUPPORT)
set(srcs ${srcs}
"src/common/bss.c"
"src/common/scan.c"

View File

@@ -260,12 +260,12 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
int ret = 0;
switch (type) {
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211KV) || defined(CONFIG_SAE_PK)
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211KV)
case WLAN_FC_STYPE_BEACON:
case WLAN_FC_STYPE_PROBE_RESP:
ret = esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf);
break;
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)*/
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
#ifdef CONFIG_IEEE80211R
case WLAN_FC_STYPE_AUTH:
ret = handle_auth_frame(frame, len, sender, rssi, channel);
@@ -328,7 +328,7 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
struct wpa_supplicant *wpa_s = &g_wpa_supp;
int ret = 0;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
#ifdef CONFIG_SUPPLICANT_TASK
if (!s_supplicant_api_lock) {
s_supplicant_api_lock = os_recursive_mutex_create();
@@ -361,7 +361,7 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
#endif /* CONFIG_IEEE80211KV */
esp_scan_init(wpa_s);
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)*/
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
wpa_s->type = 0;
wpa_s->subtype = 0;
wpa_s->type |= (1 << WLAN_FC_STYPE_ASSOC_RESP) | (1 << WLAN_FC_STYPE_REASSOC_RESP) | (1 << WLAN_FC_STYPE_AUTH);
@@ -386,13 +386,13 @@ void esp_supplicant_common_deinit(void)
{
struct wpa_supplicant *wpa_s = &g_wpa_supp;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
esp_scan_deinit(wpa_s);
#ifdef CONFIG_IEEE80211KV
wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s);
#endif /* CONFIG_IEEE80211KV */
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)*/
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
if (wpa_s->type) {
wpa_s->type = 0;
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);

View File

@@ -72,6 +72,7 @@ enum {
WPA2_AUTH_ENT_SHA384_SUITE_B = 0x0d,
WPA2_AUTH_FT_PSK = 0x0e,
WPA3_AUTH_OWE = 0x0f,
WPA3_AUTH_PSK_EXT_KEY = 0x10,
WPA2_AUTH_INVALID
};
@@ -286,7 +287,6 @@ esp_err_t esp_wifi_remain_on_channel(uint8_t ifx, uint8_t type, uint8_t channel,
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);
bool esp_wifi_is_ft_enabled_internal(uint8_t if_index);
uint8_t esp_wifi_sta_get_use_h2e_internal(void);
uint8_t esp_wifi_sta_get_config_sae_pk_internal(void);
void esp_wifi_sta_disable_sae_pk_internal(void);
void esp_wifi_sta_disable_wpa2_authmode_internal(void);
@@ -296,5 +296,6 @@ bool esp_wifi_ap_notify_node_sae_auth_done(uint8_t *mac);
bool esp_wifi_ap_is_sta_sae_reauth_node(uint8_t *mac);
uint8_t* esp_wifi_sta_get_sae_identifier_internal(void);
bool esp_wifi_eb_tx_status_success_internal(void *eb);
uint8_t* esp_wifi_sta_get_rsnxe(void);
#endif /* _ESP_WIFI_DRIVER_H_ */

View File

@@ -17,10 +17,6 @@
#include "esp_hostap.h"
#include <inttypes.h>
#ifdef CONFIG_SAE_PK
#include "common/bss.h"
extern struct wpa_supplicant g_wpa_supp;
#endif
static struct sae_pt *g_sae_pt;
static struct sae_data g_sae_data;
@@ -33,12 +29,56 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len)
{
int default_group = IANA_SECP256R1;
u32 len = 0;
uint8_t use_pt = 0;
u8 own_addr[ETH_ALEN];
const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
uint8_t use_pt = esp_wifi_sta_get_use_h2e_internal();
uint8_t sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA);
char sae_pwd_id[SAE_H2E_IDENTIFIER_LEN+1] = {0};
bool valid_pwd_id = false;
const u8 *rsnxe;
u8 rsnxe_capa = 0;
if (wpa_key_mgmt_sae_ext_key(gWpaSm.key_mgmt)) {
use_pt = 1;
}
rsnxe = esp_wifi_sta_get_rsnxe();
if (rsnxe && rsnxe[1] >= 1) {
rsnxe_capa = rsnxe[2];
}
#ifdef CONFIG_SAE_PK
bool use_pk = false;
uint8_t sae_pk_mode = esp_wifi_sta_get_config_sae_pk_internal();
if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
sae_pk_mode != WPA3_SAE_PK_MODE_DISABLED &&
((pw && sae_pk_valid_password((const char*)pw)))) {
use_pt = 1;
use_pk = true;
}
if (sae_pk_mode == WPA3_SAE_PK_MODE_ONLY && !use_pk) {
wpa_printf(MSG_DEBUG,
"SAE: Cannot use PK with the selected AP");
return ESP_FAIL;
}
#endif /* CONFIG_SAE_PK */
if (use_pt || sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
sae_pwe == SAE_PWE_BOTH) {
use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
if ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
wpa_key_mgmt_sae_ext_key(gWpaSm.key_mgmt)
#ifdef CONFIG_SAE_PK
|| (use_pk && sae_pk_mode == WPA3_SAE_PK_MODE_ONLY)
#endif /* CONFIG_SAE_PK */
) && !use_pt) {
wpa_printf(MSG_DEBUG,
"SAE: Cannot use H2E with the selected AP");
return ESP_FAIL;
}
}
if (use_pt != 0) {
memcpy(sae_pwd_id, esp_wifi_sta_get_sae_identifier_internal(), SAE_H2E_IDENTIFIER_LEN);
@@ -73,46 +113,14 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len)
return ESP_FAIL;
}
g_sae_data.akmp = gWpaSm.key_mgmt;
esp_wifi_get_macaddr_internal(WIFI_IF_STA, own_addr);
if (!bssid) {
wpa_printf(MSG_ERROR, "wpa3: cannot prepare SAE commit with no BSSID!");
return ESP_FAIL;
}
#ifdef CONFIG_SAE_PK
bool use_pk = false;
uint8_t sae_pk_mode = esp_wifi_sta_get_config_sae_pk_internal();
u8 rsnxe_capa = 0;
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, (uint8_t *)bssid);
if (!bss) {
wpa_printf(MSG_ERROR,
"SAE: BSS not available, update scan result to get BSS");
// TODO: should we trigger scan again.
return ESP_FAIL;
}
if (bss) {
const u8 *rsnxe;
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) {
rsnxe_capa = rsnxe[2];
}
}
if (use_pt && (rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
sae_pk_mode != WPA3_SAE_PK_MODE_DISABLED &&
((pw && sae_pk_valid_password((const char*)pw)))) {
use_pt = 1;
use_pk = true;
}
if (sae_pk_mode == WPA3_SAE_PK_MODE_ONLY && !use_pk) {
wpa_printf(MSG_DEBUG,
"SAE: Cannot use PK with the selected AP");
return ESP_FAIL;
}
#endif /* CONFIG_SAE_PK */
if (use_pt &&
sae_prepare_commit_pt(&g_sae_data, g_sae_pt,
own_addr, bssid, NULL, NULL) < 0) {
@@ -294,7 +302,7 @@ static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
}
g_sae_data.state = SAE_ACCEPTED;
wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmkid, true);
wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmk_len, g_sae_data.pmkid, true);
return ESP_OK;
}

View File

@@ -98,7 +98,7 @@ void wpa_supplicant_transition_disable(struct wpa_sm *sm, u8 bitmap)
wpa_printf(MSG_DEBUG, "TRANSITION_DISABLE %02x", bitmap);
if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) &&
wpa_key_mgmt_sae(sm->key_mgmt)) {
wpa_key_mgmt_sae(sm->key_mgmt)) {
esp_wifi_sta_disable_wpa2_authmode_internal();
}
}

View File

@@ -855,7 +855,8 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
*/
int wpa_use_akm_defined(int akmp){
return akmp == WPA_KEY_MGMT_OWE ||
return akmp == WPA_KEY_MGMT_OSEN ||
akmp == WPA_KEY_MGMT_OWE ||
wpa_key_mgmt_sae(akmp) ||
wpa_key_mgmt_suite_b(akmp);
}

View File

@@ -424,18 +424,6 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
//eapol_sm_notify_cached(sm->eapol);
#ifdef CONFIG_IEEE80211R
sm->xxkey_len = 0;
#ifdef CONFIG_WPA3_SAE
if ((sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) &&
sm->pmk_len == PMK_LEN) {
/* Need to allow FT key derivation to proceed with
* PMK from SAE being used as the XXKey in cases where
* the PMKID in msg 1/4 matches the PMKSA entry that was
* just added based on SAE authentication for the
* initial mobility domain association. */
os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len);
sm->xxkey_len = sm->pmk_len;
}
#endif /* CONFIG_WPA3_SAE */
#endif /* CONFIG_IEEE80211R */
} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {
int res = 0, pmk_len;
@@ -2298,18 +2286,22 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
sm->key_mgmt = WPA_KEY_MGMT_FT_PSK;
} else if (auth_mode == WPA3_AUTH_OWE) {
sm->key_mgmt = WPA_KEY_MGMT_OWE;
} else if (auth_mode == WPA3_AUTH_PSK_EXT_KEY) {
sm->key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY; /* for WPA3 PSK */
} else {
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
}
}
void wpa_set_pmk(uint8_t *pmk, const u8 *pmkid, bool cache_pmksa)
void wpa_set_pmk(uint8_t *pmk, size_t pmk_length, const u8 *pmkid, bool cache_pmksa)
{
struct wpa_sm *sm = &gWpaSm;
int pmk_len;
if (wpa_key_mgmt_sha384(sm->key_mgmt))
pmk_len = PMK_LEN_SUITE_B_192;
else if (wpa_key_mgmt_sae(sm->key_mgmt))
pmk_len = pmk_length;
else
pmk_len = PMK_LEN;
@@ -2335,7 +2327,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
/* Ideally we should use network_ctx for this purpose however currently network profile block
* is part of libraries,
* TODO Correct this in future during NVS restructuring */
if ((sm->key_mgmt == WPA_KEY_MGMT_SAE) &&
if ((sm->key_mgmt == WPA_KEY_MGMT_SAE ||
sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) &&
(os_memcmp(sm->bssid, bssid, ETH_ALEN) == 0) &&
(os_memcmp(sm->ssid, ssid, ssid_len) != 0)) {
use_pmk_cache = false;
@@ -2474,7 +2467,9 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
* Here only handle passphrase string. Need extra step to handle 32B, 64Hex raw
* PMK.
*/
if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE)
if (sm->key_mgmt == WPA_KEY_MGMT_SAE ||
sm->key_mgmt == WPA_KEY_MGMT_OWE ||
sm->key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY)
return;
/* This is really SLOW, so just re cacl while reset param */

View File

@@ -38,7 +38,7 @@ struct l2_ethhdr {
void wpa_sm_set_state(enum wpa_states state);
void wpa_set_pmk(uint8_t *pmk, const u8 *pmkid, bool cache_pmksa);
void wpa_set_pmk(uint8_t *pmk, size_t pmk_length, const u8 *pmkid, bool cache_pmksa);
int wpa_michael_mic_failure(u16 isunicast);

View File

@@ -55,6 +55,9 @@ static void print_auth_mode(int authmode)
case WIFI_AUTH_WPA3_ENT_192:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_ENT_192");
break;
case WIFI_AUTH_WPA3_EXT_PSK:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WPA3_EXT_PSK");
break;
default:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_UNKNOWN");
break;