wpa_supplicant: Add support for FT psk

This commit is contained in:
kapil.gupta
2020-07-27 14:41:40 +05:30
committed by Kapil Gupta
parent baa5b8ed7d
commit 3d5ca7ee6e
31 changed files with 2112 additions and 348 deletions

View File

@@ -20,9 +20,13 @@
#include "common/ieee802_11_common.h"
#include "esp_rrm.h"
#include "esp_wnm.h"
#include "rsn_supp/wpa_i.h"
#include "rsn_supp/wpa.h"
#if defined(CONFIG_WPA_11KV_SUPPORT) || defined(CONFIG_IEEE80211R)
struct wpa_supplicant g_wpa_supp;
#ifdef CONFIG_SUPPLICANT_TASK
static TaskHandle_t s_supplicant_task_hdl = NULL;
static void *s_supplicant_evt_queue = NULL;
static void *s_supplicant_api_lock = NULL;
@@ -50,7 +54,9 @@ static int handle_action_frm(u8 *frame, size_t len,
return 0;
}
#endif
#if defined(CONFIG_WPA_11KV_SUPPORT)
static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
u8 *payload, size_t len, u32 rssi)
{
@@ -68,7 +74,7 @@ static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
}
}
static int mgmt_rx_action(u8 *sender, u8 *payload, size_t len, u8 channel, u32 rssi)
static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, u32 rssi, u8 channel)
{
u8 category;
u8 bssid[ETH_ALEN];
@@ -80,17 +86,19 @@ static int mgmt_rx_action(u8 *sender, u8 *payload, size_t len, u8 channel, u32 r
return -1;
}
category = *payload++;
category = *frame++;
len--;
if (category == WLAN_ACTION_WNM) {
ieee802_11_rx_wnm_action(wpa_s, sender, payload, len);
ieee802_11_rx_wnm_action(wpa_s, sender, frame, len);
} else if (category == WLAN_ACTION_RADIO_MEASUREMENT) {
handle_rrm_frame(wpa_s, sender, payload, len, rssi);
handle_rrm_frame(wpa_s, sender, frame, len, rssi);
}
return 0;
}
#endif
#ifdef CONFIG_SUPPLICANT_TASK
static void btm_rrm_task(void *pvParameters)
{
supplicant_event_t *evt;
@@ -110,7 +118,7 @@ static void btm_rrm_task(void *pvParameters)
case SIG_SUPPLICANT_RX_ACTION:
{
struct ieee_mgmt_frame *frm = (struct ieee_mgmt_frame *)evt->data;
mgmt_rx_action(frm->sender, frm->payload, frm->len, frm->channel, frm->rssi);
mgmt_rx_action(frm->payload, frm->len, frm->sender, frm->rssi, frm->channel);
os_free(frm);
break;
}
@@ -142,6 +150,7 @@ static void btm_rrm_task(void *pvParameters)
/* At this point, we completed */
vTaskDelete(NULL);
}
#endif
static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
{
@@ -165,12 +174,13 @@ static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "cleared bssid flag");
}
static void register_action_frame(struct wpa_supplicant *wpa_s)
static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
{
wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION);
/* subtype is defined only for action frame */
wpa_s->subtype = 0;
#ifdef CONFIG_WPA_11KV_SUPPORT
/* current supported features in supplicant: rrm and btm */
if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA))
wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT;
@@ -179,7 +189,15 @@ static void register_action_frame(struct wpa_supplicant *wpa_s)
if (wpa_s->subtype)
wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION;
#endif
#ifdef CONFIG_IEEE80211R
/* register auth/assoc frames if FT is enabled */
if (esp_wifi_is_ft_enabled_internal(ESP_IF_WIFI_STA))
wpa_s->type |= (1 << WLAN_FC_STYPE_AUTH) |
(1 << WLAN_FC_STYPE_ASSOC_RESP) |
(1 << WLAN_FC_STYPE_REASSOC_RESP);
#endif
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
}
@@ -204,8 +222,8 @@ static void supplicant_sta_conn_handler(void* arg, esp_event_base_t event_base,
ie += sizeof(struct wpa_bss);
ieee802_11_parse_elems(wpa_s, ie, bss->ie_len);
wpa_bss_flush(wpa_s);
/* Register for action frames */
register_action_frame(wpa_s);
/* Register for mgmt frames */
register_mgmt_frames(wpa_s);
/* clear set bssid flag */
clear_bssid_flag(wpa_s);
}
@@ -216,7 +234,10 @@ static void supplicant_sta_disconn_handler(void* arg, esp_event_base_t event_bas
struct wpa_supplicant *wpa_s = &g_wpa_supp;
wifi_event_sta_disconnected_t *disconn = event_data;
#ifdef CONFIG_WPA_11KV_SUPPORT
wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s);
#endif
if (wpa_s->current_bss) {
wpa_s->current_bss = NULL;
}
@@ -226,23 +247,79 @@ static void supplicant_sta_disconn_handler(void* arg, esp_event_base_t event_bas
}
}
#ifdef CONFIG_IEEE80211R
static int handle_auth_frame(u8 *frame, size_t len,
u8 *sender, u32 rssi, u8 channel)
{
if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) {
if (gWpaSm.ft_protocol) {
if (wpa_ft_process_response(&gWpaSm, frame + 6,
len - 6, 0, sender, NULL, 0) < 0) {
wpa_sm_set_ft_params(&gWpaSm, NULL, 0);
return -1;
}
}
}
return 0;
}
static int handle_assoc_frame(u8 *frame, size_t len,
u8 *sender, u32 rssi, u8 channel)
{
if (gWpaSm.key_mgmt == WPA_KEY_MGMT_FT_PSK) {
if (gWpaSm.ft_protocol) {
if (wpa_ft_validate_reassoc_resp(&gWpaSm, frame + 6, len - 6, sender)) {
wpa_sm_set_ft_params(&gWpaSm, NULL, 0);
return -1;
}
}
wpa_sm_set_ft_params(&gWpaSm, frame + 6, len - 6);
}
return 0;
}
#endif
static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
u32 rssi, u8 channel, u64 current_tsf)
{
if (type == WLAN_FC_STYPE_BEACON || type == WLAN_FC_STYPE_PROBE_RESP) {
return esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf);
} else if (type == WLAN_FC_STYPE_ACTION) {
return handle_action_frm(frame, len, sender, rssi, channel);
int ret = 0;
switch (type) {
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;
#ifdef CONFIG_IEEE80211R
case WLAN_FC_STYPE_AUTH:
ret = handle_auth_frame(frame, len, sender, rssi, channel);
break;
case WLAN_FC_STYPE_ASSOC_RESP:
case WLAN_FC_STYPE_REASSOC_RESP:
ret = handle_assoc_frame(frame, len, sender, rssi, channel);
break;
#endif
#if defined(CONFIG_WPA_11KV_SUPPORT)
case WLAN_FC_STYPE_ACTION:
#ifdef CONFIG_SUPPLICANT_TASK
ret = handle_action_frm(frame, len, sender, rssi, channel);
#else
ret = mgmt_rx_action(frame, len, sender, rssi, channel);
#endif
break;
#endif
default:
ret = -1;
break;
}
return -1;
return ret;
}
#ifdef CONFIG_MBO
static bool bss_profile_match(u8 *sender)
bool mbo_bss_profile_match(u8 *bssid)
{
/* Incase supplicant wants drivers to skip this BSS, return false */
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, sender);
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid);
if (!bss) {
return true;
}
@@ -266,8 +343,9 @@ static bool bss_profile_match(u8 *sender)
int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
{
struct wpa_supplicant *wpa_s = &g_wpa_supp;
int ret;
int ret = 0;
#ifdef CONFIG_SUPPLICANT_TASK
s_supplicant_api_lock = xSemaphoreCreateRecursiveMutex();
if (!s_supplicant_api_lock) {
wpa_printf(MSG_ERROR, "%s: failed to create Supplicant API lock", __func__);
@@ -288,10 +366,12 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
ret = -1;
goto err;
}
esp_scan_init(wpa_s);
#endif
#ifdef CONFIG_WPA_11KV_SUPPORT
wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s);
#endif
esp_scan_init(wpa_s);
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
&supplicant_sta_conn_handler, NULL);
@@ -300,14 +380,16 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
wpa_s->type = 0;
wpa_s->subtype = 0;
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
#ifdef CONFIG_IEEE80211R
wpa_s->type |= (1 << WLAN_FC_STYPE_ASSOC_RESP) | (1 << WLAN_FC_STYPE_REASSOC_RESP) | (1 << WLAN_FC_STYPE_AUTH);
#endif
if (esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype) != ESP_OK) {
ret = -1;
goto err;
}
wpa_cb->wpa_sta_rx_mgmt = ieee80211_handle_rx_frm;
/* Matching is done only for MBO at the moment, this can be extended for other features*/
#ifdef CONFIG_MBO
wpa_cb->wpa_sta_profile_match = bss_profile_match;
dl_list_init(&wpa_s->bss_tmp_disallowed);
#else
wpa_cb->wpa_sta_profile_match = NULL;
#endif
return 0;
err:
@@ -320,8 +402,10 @@ void esp_supplicant_common_deinit(void)
struct wpa_supplicant *wpa_s = &g_wpa_supp;
esp_scan_deinit(wpa_s);
#ifdef CONFIG_WPA_11KV_SUPPORT
wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s);
#endif
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
&supplicant_sta_conn_handler);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
@@ -330,6 +414,7 @@ void esp_supplicant_common_deinit(void)
wpa_s->type = 0;
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
}
#ifdef CONFIG_SUPPLICANT_TASK
if (!s_supplicant_task_hdl && esp_supplicant_post_evt(SIG_SUPPLICANT_DEL_TASK, 0) != 0) {
if (s_supplicant_evt_queue) {
vQueueDelete(s_supplicant_evt_queue);
@@ -339,10 +424,11 @@ void esp_supplicant_common_deinit(void)
vSemaphoreDelete(s_supplicant_api_lock);
s_supplicant_api_lock = NULL;
}
wpa_printf(MSG_ERROR, "failed to send task delete event");
}
#endif
}
#ifdef CONFIG_WPA_11KV_SUPPORT
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
void *cb_ctx)
{
@@ -365,9 +451,6 @@ int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
{
int ret = wpas_mbo_update_non_pref_chan(&g_wpa_supp, non_pref_chan);
if (ret == 0) {
esp_set_assoc_ie();
}
return ret;
}
@@ -455,6 +538,24 @@ static size_t get_mbo_oce_assoc_ie(uint8_t *ie, size_t len)
return mbo_ie_len;
}
static uint8_t get_operating_class_ie(uint8_t *ie, size_t len)
{
uint8_t op_class_ie[4] = {0};
uint8_t op_class_ie_len = 2;
uint8_t *pos = op_class_ie;
*pos++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES;
*pos++ = op_class_ie_len;
#define OPER_CLASS 0x51
/* Current Operating Class */
*pos++ = OPER_CLASS;
#undef OPER_CLASS
*pos = 0;
os_memcpy(ie, op_class_ie, sizeof(op_class_ie));
return op_class_ie_len + 2;
}
#endif
static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
@@ -479,27 +580,11 @@ static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
return ext_caps_ie_len + 2;
}
static uint8_t get_operating_class_ie(uint8_t *ie, size_t len)
{
uint8_t op_class_ie[4] = {0};
uint8_t op_class_ie_len = 2;
uint8_t *pos = op_class_ie;
*pos++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES;
*pos++ = op_class_ie_len;
#define OPER_CLASS 0x51
/* Current Operating Class */
*pos++ = OPER_CLASS;
#undef OPER_CLASS
*pos = 0;
os_memcpy(ie, op_class_ie, sizeof(op_class_ie));
return op_class_ie_len + 2;
}
#endif
void esp_set_scan_ie(void)
{
#ifdef CONFIG_WPA_11KV_SUPPORT
#define SCAN_IE_LEN 64
uint8_t *ie, *pos;
size_t len = SCAN_IE_LEN, ie_len;
@@ -522,40 +607,107 @@ void esp_set_scan_ie(void)
esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0);
os_free(ie);
#undef SCAN_IE_LEN
#endif
}
void esp_set_assoc_ie(void)
#ifdef CONFIG_IEEE80211R
static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len)
{
size_t mdie_len = 0;
struct wpa_sm *sm = &gWpaSm;
/* Return if MBO IE is not enabled in driver */
if (!esp_wifi_is_ft_enabled_internal(WIFI_IF_STA)) {
return 0;
}
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid);
if (bss && wpa_key_mgmt_ft(sm->key_mgmt)) {
const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) {
const u8 *md = mdie + 2;
const u8 *wpa_md = wpa_sm_get_ft_md(sm);
if (os_memcmp(md, wpa_md,
MOBILITY_DOMAIN_ID_LEN) == 0) {
/* Add mobility domain IE */
mdie_len = wpa_ft_add_mdie(
sm, ie,
len, mdie);
}
}
}
return mdie_len;
}
#endif
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
{
#define ASSOC_IE_LEN 128
uint8_t *ie, *pos;
size_t len = ASSOC_IE_LEN, ie_len;
ie = os_malloc(ASSOC_IE_LEN);
ie = os_malloc(ASSOC_IE_LEN + ies_len);
if (!ie) {
wpa_printf(MSG_ERROR, "failed to allocate ie");
return;
}
pos = ie;
#ifdef CONFIG_WPA_11KV_SUPPORT
ie_len = get_extended_caps_ie(pos, len);
pos += ie_len;
len -= ie_len;
ie_len = get_operating_class_ie(pos, len);
pos += ie_len;
len -= ie_len;
ie_len = get_rm_enabled_ie(pos, len);
pos += ie_len;
len -= ie_len;
#ifdef CONFIG_MBO
ie_len = get_operating_class_ie(pos, len);
pos += ie_len;
len -= ie_len;
ie_len = get_mbo_oce_assoc_ie(pos, len);
pos += ie_len;
len -= ie_len;
#endif
esp_wifi_unset_appie_internal(WIFI_APPIE_ASSOC_REQ);
#endif
#ifdef CONFIG_IEEE80211R
if (mdie) {
ie_len = add_mdie(bssid, pos, len);
pos += ie_len;
len -= ie_len;
}
#endif
if (ies_len) {
os_memcpy(pos, ies, ies_len);
pos += ies_len;
len -= ies_len;
}
esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_REQ, ie, ASSOC_IE_LEN - len, 0);
os_free(ie);
#undef ASSOC_IE_LEN
}
#ifdef CONFIG_IEEE80211R
int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
const u8 *ies, size_t ies_len, bool auth_ie)
{
wpa_printf(MSG_INFO, "Updating FT IEs (len=%d)", ies_len);
if (os_memcmp(sm->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN) != 0) {
return 0;
}
/* Update auth IEs to be used in FT association */
if (auth_ie) {
esp_wifi_set_appie_internal(WIFI_APPIE_RAM_STA_AUTH, (u8 *)ies, ies_len, 0);
} else {
esp_set_assoc_ie(sm->bssid, ies, ies_len, false);
}
wpa_printf(MSG_INFO, "Updated FT IEs (len=%d) auth_ie=%d", ies_len, auth_ie);
return 0;
}
#endif
void esp_get_tx_power(uint8_t *tx_power)
{
#define DEFAULT_MAX_TX_POWER 19 /* max tx power is 19.5 dbm */
@@ -605,6 +757,7 @@ cleanup:
return ret;
}
#ifdef CONFIG_SUPPLICANT_TASK
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
{
supplicant_event_t *evt = os_zalloc(sizeof(supplicant_event_t));
@@ -631,3 +784,30 @@ int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
}
return 0;
}
#endif
#else
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
void *cb_ctx)
{
return -1;
}
int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
const char *btm_candidates,
int cand_list)
{
return -1;
}
int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
{
return -1;
}
void esp_set_scan_ie(void) { }
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
{
return 0;
}
void esp_supplicant_common_deinit(void) { }
#endif