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:
Nachiket Kukade 2020-01-20 12:17:53 +05:30
parent ebd35a1657
commit 30d6220394
16 changed files with 110 additions and 46 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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