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

@ -2010,7 +2010,6 @@ dbg_hmac_rxtx_statis_dump = 0x40001e84;
dbg_hmac_statis_dump = 0x40001e88;
ieee80211_send_action_vendor_spec = 0x40001e8c;
ieee80211_send_mgmt = 0x40001e90;
ieee80211_auth_construct = 0x40001e94;
ieee80211_vnd_lora_ie_size = 0x40001ea0;
ieee80211_vnd_ie_size = 0x40001ea4;
ieee80211_add_ssid = 0x40001ea8;
@ -2032,7 +2031,6 @@ cnx_coexist_timeout = 0x40001ee8;
sta_recv_mgmt = 0x40001eec;
ieee80211_send_setup = 0x40001ef0;
ieee80211_send_probereq = 0x40001ef4;
sta_auth_open = 0x40001ef8;
sta_auth_shared = 0x40001efc;
sta_auth_sae = 0x40001f00;
cnx_coexist_timeout_process = 0x40001f04;
@ -2046,7 +2044,6 @@ ieee80211_add_csa = 0x40001f20;
ieee80211_add_extcap = 0x40001f24;
ieee80211_regdomain_get_country = 0x40001f28;
ieee80211_add_countryie = 0x40001f2c;
ieee80211_alloc_proberesp = 0x40001f30;
ieee80211_amsdu_adjust_head = 0x40001f34;
ieee80211_amsdu_adjust_last_length = 0x40001f38;
ieee80211_amsdu_send_check = 0x40001f3c;
@ -2078,7 +2075,6 @@ ieee80211_set_max_rate = 0x40001fa4;
ic_set_sta = 0x40001fa8;
ieee80211_match_security = 0x40001fac;
ieee80211_parse_wpa = 0x40001fb0;
ieee80211_parse_rsn = 0x40001fb4;
ieee80211_add_assoc_req_ies = 0x40001fb8;
ieee80211_add_probe_req_ies = 0x40001fbc;
/* Data (.data, .bss, .rodata) */

View File

@ -249,7 +249,8 @@ typedef struct {
uint32_t rm_enabled:1; /**< Whether Radio Measurements are enabled for the connection */
uint32_t btm_enabled:1; /**< Whether BSS Transition Management is enabled for the connection */
uint32_t mbo_enabled:1; /**< Whether MBO is enabled for the connection */
uint32_t reserved:29; /**< Reserved for future feature set */
uint32_t ft_enabled:1; /**< Whether FT is enabled for the connection */
uint32_t reserved:28; /**< Reserved for future feature set */
} wifi_sta_config_t;
/** @brief Configuration data for ESP32 AP or STA.

@ -1 +1 @@
Subproject commit 39fd190dfaa5b41f564bdb3b86519bea7b7255f9
Subproject commit 3298902a408a9c57a1c3d94d38d7641c7b872d42

View File

@ -58,6 +58,7 @@ set(srcs "port/os_xtensa.c"
set(esp_srcs "esp_supplicant/src/esp_wpa2.c"
"esp_supplicant/src/esp_wpa_main.c"
"esp_supplicant/src/esp_wpas_glue.c"
"esp_supplicant/src/esp_common.c"
"esp_supplicant/src/esp_wps.c"
"esp_supplicant/src/esp_wpa3.c")
if(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
@ -147,16 +148,18 @@ else()
"src/crypto/sha256.c")
endif()
if(CONFIG_WPA_11KV_SUPPORT)
if(CONFIG_WPA_11KV_SUPPORT OR CONFIG_WPA_11R_SUPPORT)
set(roaming_src
"src/common/rrm.c"
"src/common/wnm_sta.c"
"src/common/bss.c"
"src/common/scan.c"
"src/common/ieee802_11_common.c"
"esp_supplicant/src/esp_common.c"
"esp_supplicant/src/esp_scan.c"
)
"esp_supplicant/src/esp_scan.c")
if(CONFIG_WPA_11KV_SUPPORT)
set(roaming_src ${roaming_src} "src/common/rrm.c" "src/common/wnm_sta.c")
endif()
if(CONFIG_WPA_11R_SUPPORT)
set(roaming_src ${roaming_src} "src/rsn_supp/wpa_ft.c")
endif()
else()
set(roaming_src "")
endif()
@ -180,7 +183,7 @@ idf_component_register(SRCS "${srcs}" ${esp_srcs} "${tls_src}" "${roaming_src}"
PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src
PRIV_REQUIRES mbedtls esp_timer)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-strict-aliasing -Wno-write-strings)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-strict-aliasing -Wno-write-strings -Werror)
target_compile_definitions(${COMPONENT_LIB} PRIVATE
__ets__
ESP_SUPPLICANT
@ -200,7 +203,6 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
CONFIG_ECC
CONFIG_IEEE80211W
CONFIG_SHA256
CONFIG_WNM
)
if(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE)
@ -221,11 +223,16 @@ endif()
if(CONFIG_ESP_WIFI_GMAC_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_GMAC)
endif()
if(CONFIG_WPA_MBO_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_MBO)
endif()
if(CONFIG_WPA_DPP_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_DPP)
endif()
if(CONFIG_WPA_11KV_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUPPLICANT_TASK CONFIG_WNM CONFIG_RRM)
endif()
if(CONFIG_WPA_11R_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211R)
endif()
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)

View File

@ -53,7 +53,7 @@ menu "Supplicant"
Enabling this may cause inter operability issues with some APs.
config WPA_11KV_SUPPORT
bool "Enable 802.11k, 802.11v APIs handling"
bool "Enable 802.11k, 802.11v APIs Support"
default n
help
Select this option to enable 802.11k 802.11v APIs(RRM and BTM support).
@ -77,7 +77,7 @@ menu "Supplicant"
will be flushed immediately.
config WPA_MBO_SUPPORT
bool "Enable MBO support"
bool "Enable Multi Band Operation Certification Support"
default n
select WPA_11KV_SUPPORT
select WPA_SCAN_CACHE
@ -91,4 +91,10 @@ menu "Supplicant"
help
Select this option to enable WiFi Easy Connect Support.
config WPA_11R_SUPPORT
bool "Enable 802.11R (Fast Transition)"
default n
help
Select this option to enable WiFi Fast Transition Support.
endmenu

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

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -10,8 +10,9 @@
#include "utils/includes.h"
struct wpa_funcs;
extern struct wpa_supplicant g_wpa_supp;
#ifdef ROAMING_SUPPORT
#ifdef CONFIG_WPA_11KV_SUPPORT
struct ieee_mgmt_frame {
u8 sender[ETH_ALEN];
u8 channel;
@ -38,35 +39,12 @@ enum SIG_SUPPLICANT {
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data);
void esp_get_tx_power(uint8_t *tx_power);
#ifdef CONFIG_MBO
bool mbo_bss_profile_match(u8 *bssid);
#endif
#endif
int esp_supplicant_common_init(struct wpa_funcs *wpa_cb);
void esp_supplicant_common_deinit(void);
void esp_set_scan_ie(void);
void esp_set_assoc_ie(void);
#else
#include "esp_rrm.h"
#include "esp_wnm.h"
#include "esp_mbo.h"
static inline void esp_set_scan_ie(void) { }
static inline void esp_set_assoc_ie(void) { }
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;
}
#endif
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool add_mdie);
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -18,6 +18,7 @@
#include "common/rrm.h"
#include "common/ieee802_11_common.h"
#include "esp_common_i.h"
#include "esp_scan_i.h"
#include "common/wnm_sta.h"
#include "esp_scan_i.h"
@ -36,6 +37,7 @@ static void scan_done_event_handler(void *arg, STATUS status)
esp_supplicant_handle_scan_done_evt();
}
#if defined(CONFIG_WPA_11KV_SUPPORT)
static void handle_wnm_scan_done(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss);
@ -53,6 +55,7 @@ static void handle_wnm_scan_done(struct wpa_supplicant *wpa_s)
}
}
}
#endif
static void scan_done_cleanup(struct wpa_supplicant *wpa_s)
{
@ -70,12 +73,14 @@ void esp_supplicant_handle_scan_done_evt(void)
struct wpa_supplicant *wpa_s = &g_wpa_supp;
wpa_printf(MSG_INFO, "scan done received");
#if defined(CONFIG_WPA_11KV_SUPPORT)
/* Check which module started this, call the respective function */
if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) {
wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf);
} else if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) {
handle_wnm_scan_done(wpa_s);
}
#endif
if (wpa_s->scanning) {
scan_done_cleanup(wpa_s);
}

View File

@ -49,7 +49,11 @@ typedef enum {
/* wifi_appie_t is in rom code and can't be changed anymore, use wifi_appie_ram_t for new app IEs */
typedef enum {
WIFI_APPIE_RAM_MAX = WIFI_APPIE_MAX,
WIFI_APPIE_RAM_BEACON = WIFI_APPIE_MAX,
WIFI_APPIE_RAM_PROBE_RSP,
WIFI_APPIE_RAM_STA_AUTH,
WIFI_APPIE_RAM_AP_AUTH,
WIFI_APPIE_RAM_MAX
} wifi_appie_ram_t;
enum {
@ -66,7 +70,8 @@ enum {
WAPI_AUTH_PSK = 0x0b,
WAPI_AUTH_CERT = 0x0c,
WPA2_AUTH_ENT_SHA384_SUITE_B = 0x0d,
WPA2_AUTH_INVALID = 0x0e,
WPA2_AUTH_FT_PSK = 0x0e,
WPA2_AUTH_INVALID
};
typedef enum {
@ -129,7 +134,6 @@ struct wpa_funcs {
int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
int (*wpa_sta_rx_mgmt)(u8 type, u8 *frame, size_t len, u8 *sender, u32 rssi, u8 channel, u64 current_tsf);
void (*wpa_config_done)(void);
bool (*wpa_sta_profile_match)(u8 *bssid);
};
struct wpa2_funcs {
@ -269,5 +273,6 @@ 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);
bool esp_wifi_is_ft_enabled_internal(uint8_t if_index);
#endif /* _ESP_WIFI_DRIVER_H_ */

View File

@ -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
*/
@ -66,8 +66,10 @@ void wpa_deauthenticate(u8 reason_code)
esp_wifi_deauthenticate_internal(reason_code);
}
int wpa_config_profile(void)
int wpa_config_profile(uint8_t *bssid)
{
int ret = 0;
if (esp_wifi_sta_prof_is_wpa_internal()) {
wpa_set_profile(WPA_PROTO_WPA, esp_wifi_sta_get_prof_authmode_internal());
} else if (esp_wifi_sta_prof_is_wpa2_internal() || esp_wifi_sta_prof_is_wpa3_internal()) {
@ -75,10 +77,10 @@ int wpa_config_profile(void)
} else if (esp_wifi_sta_prof_is_wapi_internal()) {
wpa_set_profile(WPA_PROTO_WAPI, esp_wifi_sta_get_prof_authmode_internal());
} else {
/* do nothing */
return -1;
ret = -1;
}
return 0;
return ret;
}
int wpa_config_bss(uint8_t *bssid)
@ -116,7 +118,6 @@ bool wpa_attach(void)
ret = (esp_wifi_register_tx_cb_internal(eapol_txcb, WIFI_TXCB_EAPOL_ID) == ESP_OK);
}
esp_set_scan_ie();
esp_set_assoc_ie();
return ret;
}
@ -169,7 +170,7 @@ int wpa_sta_connect(uint8_t *bssid)
{
/* use this API to set AP specific IEs during connection */
int ret = 0;
ret = wpa_config_profile();
ret = wpa_config_profile(bssid);
if (ret == 0) {
ret = wpa_config_bss(bssid);
if (ret) {
@ -184,7 +185,6 @@ int wpa_sta_connect(uint8_t *bssid)
void wpa_config_done(void)
{
/* used in future for setting scan and assoc IEs */
esp_set_assoc_ie();
}
int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
@ -225,19 +225,6 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
}
}
#ifndef ROAMING_SUPPORT
static inline int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
{
wpa_cb->wpa_sta_rx_mgmt = NULL;
wpa_cb->wpa_sta_profile_match = NULL;
return 0;
}
static inline void esp_supplicant_common_deinit(void)
{
}
#endif
int esp_supplicant_init(void)
{
int ret = ESP_OK;

View File

@ -159,8 +159,8 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
#define wpa_dbg(...) do {} while(0)
#endif
#define wpa_auth_logger
#define wpa_auth_vlogger
#define wpa_auth_logger(...) do {} while(0)
#define wpa_auth_vlogger(...) do {} while(0)
/**
* wpa_msg - Conditional printf for default target and ctrl_iface monitors

View File

@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SUPPLICANT_OPT_H
#define _SUPPLICANT_OPT_H
@ -29,10 +21,6 @@
#define DEBUG_PRINT
#endif
#if CONFIG_WPA_11KV_SUPPORT
#define ROAMING_SUPPORT 1
#endif
#if CONFIG_WPA_SCAN_CACHE
#define SCAN_CACHE_SUPPORTED
#endif

View File

@ -39,12 +39,12 @@ static int wpa_sm_step(struct wpa_state_machine *sm);
static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data,
size_t data_len);
static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
struct wpa_group *group);
static void wpa_request_new_ptk(struct wpa_state_machine *sm);
static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
struct wpa_group *group);
static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
struct wpa_group *group);
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
@ -221,7 +221,7 @@ static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth,
static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
{
int ret = 0;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
ret = 1;
#endif /* CONFIG_IEEE80211R */
@ -365,7 +365,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
return NULL;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init();
if (wpa_auth->ft_pmk_cache == NULL) {
wpa_printf( MSG_ERROR, "FT PMK cache initialization failed.");
@ -374,7 +374,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
os_free(wpa_auth);
return NULL;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
return wpa_auth;
}
@ -402,14 +402,14 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
return -1;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (sm->ft_completed) {
wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
"FT authentication already completed - do not "
"start 4-way handshake");
return 0;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
if (sm->started) {
memset(&sm->key_replay, 0, sizeof(sm->key_replay));
@ -447,9 +447,10 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
sm->group->GKeyDoneStations--;
sm->GUpdateStationKeys = FALSE;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
os_free(sm->assoc_resp_ftie);
#endif /* CONFIG_IEEE80211R */
wpabuf_free(sm->ft_pending_req_ies);
#endif /* CONFIG_IEEE80211R_AP */
wpa_printf( MSG_DEBUG, "wpa_free_sta_sm: free eapol=%p\n", sm->last_rx_eapol_key);
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
@ -513,7 +514,7 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr,
}
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
static int ICACHE_FLASH_ATTR ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
struct wpa_eapol_ie_parse *kde)
@ -560,7 +561,7 @@ static int ICACHE_FLASH_ATTR ft_check_msg_2_of_4(struct wpa_authenticator *wpa_a
return 0;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int group)
@ -786,12 +787,12 @@ continue_processing:
wpa_sta_disconnect(wpa_auth, sm->addr);
return;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr);
return;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
break;
case PAIRWISE_4:
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
@ -1095,25 +1096,28 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
buf, key_data_len);
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
if (aes_wrap(sm->PTK.kek, 16, (key_data_len - 8) / 8, buf,
if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, (key_data_len - 8) / 8, buf,
(u8 *) (key + 1))) {
os_free(hdr);
os_free(buf);
return;
}
WPA_PUT_BE16(key->key_data_length, key_data_len);
} else {
} else if (sm->PTK.kek_len == 16) {
u8 ek[32];
memcpy(key->key_iv,
sm->group->Counter + WPA_NONCE_LEN - 16, 16);
inc_byte_array(sm->group->Counter, WPA_NONCE_LEN);
memcpy(ek, key->key_iv, 16);
memcpy(ek + 16, sm->PTK.kek, 16);
memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len);
memcpy(key + 1, buf, key_data_len);
rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len);
WPA_PUT_BE16(key->key_data_length, key_data_len);
} else {
os_free(buf);
os_free(hdr);
return;
}
os_free(buf);
}
if (key_info & WPA_KEY_INFO_MIC) {
@ -1280,7 +1284,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
sm->ReAuthenticationRequest = TRUE;
break;
case WPA_ASSOC_FT:
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
wpa_printf( MSG_DEBUG, "FT: Retry PTK configuration "
"after association");
wpa_ft_install_ptk(sm);
@ -1288,14 +1292,14 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
/* Using FT protocol, not WPA auth state machine */
sm->ft_completed = 1;
return 0;
#else /* CONFIG_IEEE80211R */
#else /* CONFIG_IEEE80211R_AP */
break;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
sm->ft_completed = 0;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
if (sm->mgmt_frame_prot && event == WPA_AUTH)
@ -1438,20 +1442,20 @@ SM_STATE(WPA_PTK, INITPMK)
size_t len = 2 * PMK_LEN;
SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk);
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
sm->xxkey_len = 0;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
wpa_printf( MSG_DEBUG, "WPA: PMK from EAPOL state machine "
"(len=%lu)", (unsigned long) len);
memcpy(sm->PMK, msk, PMK_LEN);
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (len >= 2 * PMK_LEN) {
memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
sm->xxkey_len = PMK_LEN;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
} else {
wpa_printf( MSG_DEBUG, "WPA: Could not get PMK");
}
@ -1476,10 +1480,10 @@ SM_STATE(WPA_PTK, INITPSK)
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);
if (psk) {
memcpy(sm->PMK, psk, PMK_LEN);
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
}
sm->req_replay_counter_used = 0;
}
@ -1532,12 +1536,13 @@ SM_STATE(WPA_PTK, PTKSTART)
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, struct wpa_ptk *ptk)
{
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64;
size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64;
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
#endif /* CONFIG_IEEE80211R */
return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
#endif /* CONFIG_IEEE80211R_AP */
return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
@ -1592,7 +1597,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
return;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
/*
* Verify that PMKR1Name from EAPOL-Key message 2/4 matches
@ -1608,7 +1613,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
return;
}
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
@ -1763,12 +1768,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
kde_len = wpa_ie_len + ieee80211w_kde_len(sm);
if (gtk)
kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
kde_len += 300; /* FTIE + 2 * TIE */
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
kde = (u8 *)os_malloc(kde_len);
if (kde == NULL)
return;
@ -1776,7 +1781,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
pos = kde;
memcpy(pos, wpa_ie, wpa_ie_len);
pos += wpa_ie_len;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name);
if (res < 0) {
@ -1787,7 +1792,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
}
pos += res;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
if (gtk) {
u8 hdr[2];
hdr[0] = keyidx & 0x03;
@ -1797,7 +1802,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
}
pos = ieee80211w_kde_add(sm, pos);
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res;
struct wpa_auth_config *conf;
@ -1829,7 +1834,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60);
pos += 4;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
wpa_send_eapol(sm->wpa_auth, sm,
(secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
@ -1889,9 +1894,9 @@ SM_STATE(WPA_PTK, PTKINITDONE)
{
esp_wifi_wpa_ptk_init_done_internal(sm->addr);
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
}

View File

@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -83,7 +83,7 @@ struct wpa_state_machine {
unsigned int mgmt_frame_prot:1;
unsigned int rx_eapol_key_secure:1;
unsigned int update_snonce:1;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
unsigned int ft_completed:1;
unsigned int pmk_r1_name_valid:1;
#endif /* CONFIG_IEEE80211R */
@ -103,9 +103,12 @@ struct wpa_state_machine {
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
#ifdef CONFIG_IEEE80211R
u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
#ifdef CONFIG_IEEE80211R_AP
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
* first 384 bits of MSK */
size_t xxkey_len;
u8 pmk_r1[PMK_LEN_MAX];
unsigned int pmk_r1_len;
u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth
* Request */
u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
@ -113,7 +116,17 @@ struct wpa_state_machine {
u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
* message 2/4 */
u8 *assoc_resp_ftie;
#endif /* CONFIG_IEEE80211R */
void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid,
u16 auth_transaction, u16 status,
const u8 *ies, size_t ies_len);
void *ft_pending_cb_ctx;
struct wpabuf *ft_pending_req_ies;
u8 ft_pending_pull_nonce[FT_RRB_NONCE_LEN];
u8 ft_pending_auth_transaction;
u8 ft_pending_current_ap[ETH_ALEN];
int ft_pending_pull_left_retries;
#endif /* CONFIG_IEEE80211R_AP */
int pending_1_of_4_timeout;
u32 index;
@ -165,6 +178,10 @@ struct wpa_authenticator {
size_t wpa_ie_len;
u8 addr[ETH_ALEN];
#ifdef CONFIG_IEEE80211R
struct rsn_pmksa_cache *pmksa;
struct wpa_ft_pmk_cache *ft_pmk_cache;
#endif
};

View File

@ -160,7 +160,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
pos += RSN_SELECTOR_LEN;
@ -171,7 +171,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
@ -314,7 +314,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
return res;
pos += res;
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
res = wpa_write_mdie(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
@ -322,7 +322,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
return res;
pos += res;
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
res = wpa_write_wpa_ie(&wpa_auth->conf,
pos, buf + sizeof(buf) - pos);
@ -392,12 +392,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
if (0) {
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
selector = RSN_AUTH_KEY_MGMT_FT_PSK;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
@ -467,12 +467,12 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
}
if (0) {
}
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
@ -542,7 +542,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
sm->mgmt_frame_prot = 1;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
wpa_printf( MSG_DEBUG, "RSN: Trying to use FT, but "
@ -556,7 +556,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_INVALID_MDIE;
}
}
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
if (ciphers & WPA_CIPHER_CCMP)
sm->pairwise = WPA_CIPHER_CCMP;
@ -700,14 +700,14 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
if (*pos == WLAN_EID_RSN) {
ie->rsn_ie = pos;
ie->rsn_ie_len = pos[1] + 2;
#ifdef CONFIG_IEEE80211R
#ifdef CONFIG_IEEE80211R_AP
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
ie->mdie = pos;
ie->mdie_len = pos[1] + 2;
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
ie->ftie = pos;
ie->ftie_len = pos[1] + 2;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R_AP */
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)

View File

@ -10,6 +10,7 @@
#define BSS_H
struct wpa_scan_res;
struct wpa_supplicant;
/**
* struct wpa_bss - BSS table

View File

@ -25,7 +25,6 @@ struct dpp_global;
#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */
#define DPP_TCP_PORT 7871
#define SSID_MAX_LEN 32
#define PMKID_LEN 16
#define PMK_LEN 32
#define PMK_LEN_SUITE_B_192 48

View File

@ -6,9 +6,9 @@
* See README for more details.
*/
#include "utils/includes.h"
#include "includes.h"
#include "utils/common.h"
#include "common.h"
#include "defs.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
@ -37,6 +37,22 @@ const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
return NULL;
}
int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
{
const struct element *elem;
int count = 0;
if (ies == NULL)
return 0;
for_each_element(elem, ies, ies_len)
count++;
return count;
}
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type)
{
const struct element *elem;
@ -50,6 +66,7 @@ const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type)
return NULL;
}
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
{
/*
@ -184,6 +201,7 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
*/
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len)
{
#ifdef CONFIG_RRM
const struct element *elem;
if (!start)
@ -192,7 +210,6 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t
for_each_element(elem, start, len) {
u8 id = elem->id;
const u8 *pos = elem->data;
switch (id) {
case WLAN_EID_RRM_ENABLED_CAPABILITIES:
os_memcpy(wpa_s->rrm_ie, pos, 5);
@ -207,6 +224,7 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t
}
}
#endif
return 0;
}

View File

@ -42,4 +42,5 @@ int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
u8 get_operating_class(u8 chan, int sec_channel);
int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
#endif /* IEEE802_11_COMMON_H */

View File

@ -46,12 +46,14 @@ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
wpa_printf(MSG_ERROR, "Memory allocation failed");
return;
}
#ifdef CONFIG_WNM
if (wpa_s->wnm_mode) {
/* Use the same memory */
params->ssids[0].ssid = wpa_s->current_bss->ssid;
params->ssids[0].ssid_len = wpa_s->current_bss->ssid_len;
params->num_ssids = 1;
}
#endif
if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
/* Use the same memory */
params->bssid = wpa_s->next_scan_bssid;

View File

@ -1,15 +1,9 @@
/*
* WPA/RSN - Shared functions for supplicant and authenticator
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifdef ESP_SUPPLICANT
@ -25,8 +19,221 @@
#include "crypto/md5.h"
#include "crypto/aes.h"
#include "crypto/aes_wrap.h"
#include "crypto/crypto.h"
#define MD5_MAC_LEN 16
#ifdef CONFIG_IEEE80211R
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *ap_addr, u8 transaction_seqnum,
const u8 *mdie, size_t mdie_len,
const u8 *ftie, size_t ftie_len,
const u8 *rsnie, size_t rsnie_len,
const u8 *ric, size_t ric_len, u8 *mic)
{
u8 *buf, *pos;
size_t buf_len;
if (kck_len != 16) {
wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
(unsigned int) kck_len);
return -1;
}
buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
buf = os_malloc(buf_len);
if (buf == NULL)
return -1;
pos = buf;
os_memcpy(pos, sta_addr, ETH_ALEN);
pos += ETH_ALEN;
os_memcpy(pos, ap_addr, ETH_ALEN);
pos += ETH_ALEN;
*pos++ = transaction_seqnum;
if (rsnie) {
os_memcpy(pos, rsnie, rsnie_len);
pos += rsnie_len;
}
if (mdie) {
os_memcpy(pos, mdie, mdie_len);
pos += mdie_len;
}
if (ftie) {
struct rsn_ftie *_ftie;
os_memcpy(pos, ftie, ftie_len);
if (ftie_len < 2 + sizeof(*_ftie)) {
os_free(buf);
return -1;
}
_ftie = (struct rsn_ftie *) (pos + 2);
os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
pos += ftie_len;
}
if (ric) {
os_memcpy(pos, ric, ric_len);
pos += ric_len;
}
wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
if (omac1_aes_128(kck, buf, pos - buf, mic)) {
os_free(buf);
return -1;
}
os_free(buf);
return 0;
}
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
parse->ftie = ie;
parse->ftie_len = ie_len;
pos = ie + sizeof(struct rsn_ftie);
end = ie + ie_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case FTIE_SUBELEM_R1KH_ID:
if (pos[1] != FT_R1KH_ID_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r1kh_id = pos + 2;
break;
case FTIE_SUBELEM_GTK:
parse->gtk = pos + 2;
parse->gtk_len = pos[1];
break;
case FTIE_SUBELEM_R0KH_ID:
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
"length in FTIE: %d", pos[1]);
return -1;
}
parse->r0kh_id = pos + 2;
parse->r0kh_id_len = pos[1];
break;
#ifdef CONFIG_IEEE80211W
case FTIE_SUBELEM_IGTK:
parse->igtk = pos + 2;
parse->igtk_len = pos[1];
break;
#endif /* CONFIG_IEEE80211W */
}
pos += 2 + pos[1];
}
return 0;
}
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
struct wpa_ft_ies *parse)
{
const u8 *end, *pos;
struct wpa_ie_data data;
int ret;
const struct rsn_ftie *ftie;
int prot_ie_count = 0;
os_memset(parse, 0, sizeof(*parse));
if (ies == NULL)
return 0;
pos = ies;
end = ies + ies_len;
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
switch (pos[0]) {
case WLAN_EID_RSN:
parse->rsn = pos + 2;
parse->rsn_len = pos[1];
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
parse->rsn_len + 2,
&data);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse "
"RSN IE: %d", ret);
return -1;
}
if (data.num_pmkid == 1 && data.pmkid)
parse->rsn_pmkid = data.pmkid;
break;
case WLAN_EID_MOBILITY_DOMAIN:
parse->mdie = pos + 2;
parse->mdie_len = pos[1];
break;
case WLAN_EID_FAST_BSS_TRANSITION:
if (pos[1] < sizeof(*ftie))
return -1;
ftie = (const struct rsn_ftie *) (pos + 2);
prot_ie_count = ftie->mic_control[1];
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
parse->tie = pos + 2;
parse->tie_len = pos[1];
break;
case WLAN_EID_RIC_DATA:
if (parse->ric == NULL)
parse->ric = pos;
break;
}
pos += 2 + pos[1];
}
if (prot_ie_count == 0)
return 0; /* no MIC */
/*
* Check that the protected IE count matches with IEs included in the
* frame.
*/
if (parse->rsn)
prot_ie_count--;
if (parse->mdie)
prot_ie_count--;
if (parse->ftie)
prot_ie_count--;
if (prot_ie_count < 0) {
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
"the protected IE count");
return -1;
}
if (prot_ie_count == 0 && parse->ric) {
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
"included in protected IE count");
return -1;
}
/* Determine the end of the RIC IE(s) */
pos = parse->ric;
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
prot_ie_count) {
prot_ie_count--;
pos += 2 + pos[1];
}
parse->ric_len = pos - parse->ric;
if (prot_ie_count) {
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
"frame", (int) prot_ie_count);
return -1;
}
return 0;
}
#endif /* CONFIG_IEEE80211R */
static unsigned int wpa_kck_len(int akmp)
{
@ -113,6 +320,10 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif
#ifdef CONFIG_WPA3_SAE
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
return WPA_KEY_MGMT_SAE;
#endif /* CONFIG_WPA3_SAE */
return 0;
}
@ -164,7 +375,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
int left;
int i, count;
memset(data, 0, sizeof(*data));
os_memset(data, 0, sizeof(*data));
data->proto = WPA_PROTO_RSN;
data->pairwise_cipher = WPA_CIPHER_CCMP;
data->group_cipher = WPA_CIPHER_CCMP;
@ -181,10 +392,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
#ifdef DEBUG_PRINT
#ifdef DEBUG_PRINT
wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
__func__, (unsigned long) rsn_ie_len);
#endif
#endif
return -1;
}
@ -193,10 +404,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
if (hdr->elem_id != WLAN_EID_RSN ||
hdr->len != rsn_ie_len - 2 ||
WPA_GET_LE16(hdr->version) != RSN_VERSION) {
#ifdef DEBUG_PRINT
#ifdef DEBUG_PRINT
wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
__func__);
#endif
#endif
return -2;
}
@ -208,10 +419,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
} else if (left > 0) {
#ifdef DEBUG_PRINT
#ifdef DEBUG_PRINT
wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
__func__, left);
#endif
#endif
return -3;
}
@ -423,6 +634,194 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
return 0;
}
#ifdef CONFIG_IEEE80211R
/**
* wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
*
* IEEE Std 802.11r-2008 - 8.5.1.5.3
*/
void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
const u8 *ssid, size_t ssid_len,
const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
{
u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
FT_R0KH_ID_MAX_LEN + ETH_ALEN];
u8 *pos, r0_key_data[48], hash[32];
const u8 *addr[2];
size_t len[2];
/*
* R0-Key-Data = KDF-384(XXKey, "FT-R0",
* SSIDlength || SSID || MDID || R0KHlength ||
* R0KH-ID || S0KH-ID)
* XXKey is either the second 256 bits of MSK or PSK.
* PMK-R0 = L(R0-Key-Data, 0, 256)
* PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
*/
if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
return;
pos = buf;
*pos++ = ssid_len;
os_memcpy(pos, ssid, ssid_len);
pos += ssid_len;
os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
pos += MOBILITY_DOMAIN_ID_LEN;
*pos++ = r0kh_id_len;
os_memcpy(pos, r0kh_id, r0kh_id_len);
pos += r0kh_id_len;
os_memcpy(pos, s0kh_id, ETH_ALEN);
pos += ETH_ALEN;
sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
r0_key_data, sizeof(r0_key_data));
os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
/*
* PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
*/
addr[0] = (const u8 *) "FT-R0N";
len[0] = 6;
addr[1] = r0_key_data + PMK_LEN;
len[1] = 16;
sha256_vector(2, addr, len, hash);
os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
}
/**
* wpa_derive_pmk_r1_name - Derive PMKR1Name
*
* IEEE Std 802.11r-2008 - 8.5.1.5.4
*/
void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
const u8 *s1kh_id, u8 *pmk_r1_name)
{
u8 hash[32];
const u8 *addr[4];
size_t len[4];
/*
* PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
* R1KH-ID || S1KH-ID))
*/
addr[0] = (const u8 *) "FT-R1N";
len[0] = 6;
addr[1] = pmk_r0_name;
len[1] = WPA_PMK_NAME_LEN;
addr[2] = r1kh_id;
len[2] = FT_R1KH_ID_LEN;
addr[3] = s1kh_id;
len[3] = ETH_ALEN;
sha256_vector(4, addr, len, hash);
os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
}
/**
* wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
*
* IEEE Std 802.11r-2008 - 8.5.1.5.4
*/
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
const u8 *r1kh_id, const u8 *s1kh_id,
u8 *pmk_r1, u8 *pmk_r1_name)
{
u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
u8 *pos;
/* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
pos = buf;
os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
pos += FT_R1KH_ID_LEN;
os_memcpy(pos, s1kh_id, ETH_ALEN);
pos += ETH_ALEN;
sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
}
/**
* wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
*
* IEEE Std 802.11r-2008 - 8.5.1.5.5
*/
int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
const u8 *sta_addr, const u8 *bssid,
const u8 *pmk_r1_name,
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
{
u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
u8 *pos, hash[32];
const u8 *addr[6];
size_t len[6];
u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
size_t ptk_len;
/*
* PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
* BSSID || STA-ADDR)
*/
pos = buf;
os_memcpy(pos, snonce, WPA_NONCE_LEN);
pos += WPA_NONCE_LEN;
os_memcpy(pos, anonce, WPA_NONCE_LEN);
pos += WPA_NONCE_LEN;
os_memcpy(pos, bssid, ETH_ALEN);
pos += ETH_ALEN;
os_memcpy(pos, sta_addr, ETH_ALEN);
pos += ETH_ALEN;
ptk->kck_len = wpa_kck_len(akmp);
ptk->kek_len = wpa_kek_len(akmp);
ptk->tk_len = wpa_cipher_key_len(cipher);
ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len);
/*
* PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
* ANonce || BSSID || STA-ADDR))
*/
addr[0] = pmk_r1_name;
len[0] = WPA_PMK_NAME_LEN;
addr[1] = (const u8 *) "FT-PTKN";
len[1] = 7;
addr[2] = snonce;
len[2] = WPA_NONCE_LEN;
addr[3] = anonce;
len[3] = WPA_NONCE_LEN;
addr[4] = bssid;
len[4] = ETH_ALEN;
addr[5] = sta_addr;
len[5] = ETH_ALEN;
sha256_vector(6, addr, len, hash);
os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
os_memcpy(ptk->kck, tmp, ptk->kck_len);
os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
os_memset(tmp, 0, sizeof(tmp));
return 0;
}
#endif /* CONFIG_IEEE80211R */
/**
* wpa_eapol_key_mic - Calculate EAPOL-Key MIC
* @key: EAPOL-Key Key Confirmation Key (KCK)
@ -500,7 +899,7 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
if (ie1 == NULL || ie2 == NULL)
return -1;
if (ie1len == ie2len && memcmp(ie1, ie2, ie1len) == 0)
if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
return 0; /* identical IEs */
#ifdef CONFIG_IEEE80211R
@ -751,6 +1150,108 @@ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
memcpy(pmkid, hash, PMKID_LEN);
}
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
{
u8 *start, *end, *rpos, *rend;
int added = 0;
start = ies;
end = ies + *ies_len;
while (start < end) {
if (*start == WLAN_EID_RSN)
break;
start += 2 + start[1];
}
if (start >= end) {
wpa_printf(MSG_ERROR, "RSN: Could not find RSNE in IEs data");
return -1;
}
wpa_hexdump(MSG_DEBUG, "RSN: RSNE before modification",
start, 2 + start[1]);
/* Find start of PMKID-Count */
rpos = start + 2;
rend = rpos + start[1];
/* Skip Version and Group Data Cipher Suite */
rpos += 2 + 4;
/* Skip Pairwise Cipher Suite Count and List */
rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
/* Skip AKM Suite Count and List */
rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
if (rpos == rend) {
/* Add RSN Capabilities */
os_memmove(rpos + 2, rpos, end - rpos);
*rpos++ = 0;
*rpos++ = 0;
added += 2;
start[1] += 2;
rend = rpos;
} else {
/* Skip RSN Capabilities */
rpos += 2;
if (rpos > rend) {
wpa_printf(MSG_ERROR,
"RSN: Could not parse RSNE in IEs data");
return -1;
}
}
if (rpos == rend) {
/* No PMKID-Count field included; add it */
os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos);
WPA_PUT_LE16(rpos, 1);
rpos += 2;
os_memcpy(rpos, pmkid, PMKID_LEN);
added += 2 + PMKID_LEN;
start[1] += 2 + PMKID_LEN;
} else {
u16 num_pmkid;
if (rend - rpos < 2)
return -1;
num_pmkid = WPA_GET_LE16(rpos);
/* PMKID-Count was included; use it */
if (num_pmkid != 0) {
u8 *after;
if (num_pmkid * PMKID_LEN > rend - rpos - 2)
return -1;
/*
* PMKID may have been included in RSN IE in
* (Re)Association Request frame, so remove the old
* PMKID(s) first before adding the new one.
*/
wpa_printf(MSG_DEBUG,
"RSN: Remove %u old PMKID(s) from RSNE",
num_pmkid);
after = rpos + 2 + num_pmkid * PMKID_LEN;
os_memmove(rpos + 2, after, end - after);
start[1] -= num_pmkid * PMKID_LEN;
added -= num_pmkid * PMKID_LEN;
}
WPA_PUT_LE16(rpos, 1);
rpos += 2;
os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos);
os_memcpy(rpos, pmkid, PMKID_LEN);
added += PMKID_LEN;
start[1] += PMKID_LEN;
}
wpa_hexdump(MSG_DEBUG, "RSN: RSNE after modification (PMKID inserted)",
start, 2 + start[1]);
*ies_len += added;
return 0;
}
int wpa_cipher_key_len(int cipher)
{
switch (cipher) {
@ -813,6 +1314,17 @@ int wpa_cipher_to_alg(int cipher)
return WIFI_WPA_ALG_NONE;
}
int wpa_cipher_valid_pairwise(int cipher)
{
return cipher == WPA_CIPHER_GCMP_256 ||
cipher == WPA_CIPHER_CCMP ||
cipher == WPA_CIPHER_GCMP ||
cipher == WPA_CIPHER_TKIP;
}
u32 wpa_cipher_to_suite(int proto, int cipher)
{
if (cipher & WPA_CIPHER_CCMP)

View File

@ -1,15 +1,9 @@
/*
* WPA definitions shared between hostapd and wpa_supplicant
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "os.h"
@ -71,7 +65,7 @@
#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \
RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
@ -332,6 +326,29 @@ struct rsn_rdie {
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211R
int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
const u8 *ap_addr, u8 transaction_seqnum,
const u8 *mdie, size_t mdie_len,
const u8 *ftie, size_t ftie_len,
const u8 *rsnie, size_t rsnie_len,
const u8 *ric, size_t ric_len, u8 *mic);
void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
const u8 *ssid, size_t ssid_len,
const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name);
void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
const u8 *s1kh_id, u8 *pmk_r1_name);
void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
const u8 *r1kh_id, const u8 *s1kh_id,
u8 *pmk_r1, u8 *pmk_r1_name);
int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
const u8 *sta_addr, const u8 *bssid,
const u8 *pmk_r1_name,
struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher);
#endif /* CONFIG_IEEE80211R */
struct wpa_ie_data {
int proto;
int pairwise_cipher;
@ -380,6 +397,30 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
int wpa_compare_rsn_ie(int ft_initial_assoc,
const u8 *ie1, size_t ie1len,
const u8 *ie2, size_t ie2len);
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
struct wpa_ft_ies {
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
const u8 *r1kh_id;
const u8 *gtk;
size_t gtk_len;
const u8 *r0kh_id;
size_t r0kh_id_len;
const u8 *rsn;
size_t rsn_len;
const u8 *rsn_pmkid;
const u8 *tie;
size_t tie_len;
const u8 *igtk;
size_t igtk_len;
const u8 *ric;
size_t ric_len;
};
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
const u8 *buf, size_t len, u8 *mic);
@ -394,6 +435,7 @@ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
int wpa_cipher_key_len(int cipher);
int wpa_cipher_rsc_len(int cipher);
int wpa_cipher_to_alg(int cipher);
int wpa_cipher_valid_pairwise(int cipher);
int wpa_cipher_valid_mgmt_group(int cipher);
u32 wpa_cipher_to_suite(int proto, int cipher);

View File

@ -71,11 +71,6 @@ enum scan_trigger_reason {
};
struct wpa_supplicant {
int disable_btm;
unsigned int disable_mbo_oce;
/* rrm ie */
uint8_t rrm_ie[5];
u8 extend_caps[8];
int scanning;
enum scan_trigger_reason scan_reason;
@ -105,6 +100,9 @@ struct wpa_supplicant {
uint32_t type, subtype;
u8 next_scan_chan;
#ifdef CONFIG_WNM
int disable_btm;
unsigned int disable_mbo_oce;
u8 extend_caps[8];
u8 wnm_dialog_token;
u8 wnm_reply;
u8 wnm_num_neighbor_report;
@ -136,9 +134,13 @@ struct wpa_supplicant {
struct dl_list bss_tmp_disallowed;
#endif /* CONFIG_MBO */
#endif /* CONFIG_WNM */
#ifdef CONFIG_RRM
/* rrm ie */
uint8_t rrm_ie[5];
struct rrm_data rrm;
struct beacon_rep_data beacon_rep_data;
struct os_reltime beacon_rep_scan;
#endif
};
struct non_pref_chan_s;

View File

@ -29,6 +29,8 @@
#include "crypto/aes_wrap.h"
#include "crypto/ccmp.h"
#include "esp_rom_sys.h"
#include "common/bss.h"
#include "esp_common_i.h"
/**
* eapol_sm_notify_eap_success - Notification of external EAP success trigger
@ -54,12 +56,6 @@ u8 assoc_ie_buf[ASSOC_IE_LEN+2];
void set_assoc_ie(u8 * assoc_buf);
static int wpa_sm_set_key(struct install_key *sm, enum wpa_alg alg,
u8 *addr, int key_idx, int set_tx,
u8 *seq, size_t seq_len,
u8 *key, size_t key_len,
enum key_flag key_flag);
static int wpa_sm_get_key(uint8_t *ifx, int *alg, u8 *addr, int *key_idx, u8 *key, size_t key_len, enum key_flag key_flag);
void wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len);
@ -230,8 +226,8 @@ static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 prot
* @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
*/
void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
int ver, const u8 *dest, u16 proto,
u8 *msg, size_t msg_len, u8 *key_mic)
int ver, const u8 *dest, u16 proto,
u8 *msg, size_t msg_len, u8 *key_mic)
{
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
/*
@ -542,6 +538,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
struct wpa_eapol_key_192 *reply192;
u8 *rsn_ie_buf = NULL;
u8 *rbuf, *key_mic;
if (wpa_ie == NULL) {
@ -552,6 +549,43 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
return -1;
}
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
int res;
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE before FT processing",
wpa_ie, wpa_ie_len);
/*
* Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
* FTIE from (Re)Association Response.
*/
rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
sm->assoc_resp_ies_len);
if (rsn_ie_buf == NULL)
return -1;
os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
sm->pmk_r1_name);
if (res < 0) {
os_free(rsn_ie_buf);
return -1;
}
wpa_hexdump(MSG_DEBUG,
"WPA: WPA IE after PMKID[PMKR1Name] addition into RSNE",
rsn_ie_buf, wpa_ie_len);
if (sm->assoc_resp_ies) {
wpa_hexdump(MSG_DEBUG, "WPA: Add assoc_resp_ies",
sm->assoc_resp_ies,
sm->assoc_resp_ies_len);
os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
sm->assoc_resp_ies_len);
wpa_ie_len += sm->assoc_resp_ies_len;
}
wpa_ie = rsn_ie_buf;
}
#endif /* CONFIG_IEEE80211R */
wpa_hexdump(MSG_MSGDUMP, "WPA: WPA IE for msg 2/4\n", wpa_ie, wpa_ie_len);
mic_len = wpa_mic_len(sm->key_mgmt);
@ -560,6 +594,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
NULL, hdrlen + wpa_ie_len,
&rlen, (void *) &reply);
if (rbuf == NULL) {
os_free(rsn_ie_buf);
return -1;
}
reply192 = (struct wpa_eapol_key_192 *) reply;
@ -585,7 +620,8 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
}
memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
os_free(rsn_ie_buf);
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 2/4\n");
@ -599,6 +635,10 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
{
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt))
return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
#endif /* CONFIG_IEEE80211R */
return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
sm->own_addr, sm->bssid, sm->snonce,
key->key_nonce, ptk, sm->key_mgmt,
@ -783,7 +823,13 @@ void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
* the target AP.
*/
}
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt)) {
/* Prepare for the next transition */
wpa_ft_prepare_auth_request(sm, NULL);
sm->ft_protocol = 1;
}
#endif /* CONFIG_IEEE80211R */
}
static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
@ -1918,6 +1964,9 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
"allow invalid version for non-CCMP group "
"keys");
#endif
} else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
wpa_printf(MSG_DEBUG,
"WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
} else
goto out;
}
@ -2178,6 +2227,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
sm->key_mgmt = WPA_KEY_MGMT_WAPI_PSK; /* for WAPI PSK */
} else if (auth_mode == WPA2_AUTH_ENT_SHA384_SUITE_B) {
sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
} else if (auth_mode == WPA2_AUTH_FT_PSK) {
sm->key_mgmt = WPA_KEY_MGMT_FT_PSK;
} else {
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
}
@ -2251,7 +2302,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
#ifdef CONFIG_SUITEB192
extern bool g_wpa_suiteb_certification;
if (g_wpa_suiteb_certification) {
if (mgmt_cipher != WIFI_CIPHER_TYPE_AES_GMAC256) {
if (sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256) {
wpa_printf(MSG_ERROR, "suite-b 192bit certification, only GMAC256 is supported");
return -1;
}
@ -2261,13 +2312,46 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
memset(&sm->pmf_cfg, 0, sizeof(sm->pmf_cfg));
sm->mgmt_group_cipher = WPA_CIPHER_NONE;
}
#endif
#ifdef CONFIG_IEEE80211R
if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) {
const u8 *ie, *md = NULL;
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, (uint8_t *)bssid);
if (!bss) {
return -1;
}
ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
md = ie + 2;
if (os_memcmp(md, sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) {
/* Reset Auth IE here */
esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_STA_AUTH);
esp_wifi_unset_appie_internal(WIFI_APPIE_ASSOC_REQ);
sm->ft_protocol = 0;
}
wpa_sm_set_ft_params(sm, ie, ie ? 2 + ie[1] : 0);
} else {
/* Reset FT parameters */
wpa_sm_set_ft_params(sm, NULL, 0);
esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_STA_AUTH);
esp_wifi_unset_appie_internal(WIFI_APPIE_ASSOC_REQ);
}
#endif
set_assoc_ie(assoc_ie_buf); /* use static buffer */
res = wpa_gen_wpa_ie(sm, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
if (res < 0)
return -1;
sm->assoc_wpa_ie_len = res;
esp_set_assoc_ie((uint8_t *)bssid, NULL, 0, true);
os_memset(sm->ssid, 0, sizeof(sm->ssid));
os_memcpy(sm->ssid, ssid, ssid_len);
sm->ssid_len = ssid_len;
wpa_set_passphrase(passphrase, ssid, ssid_len);
#ifdef CONFIG_MBO
if (!mbo_bss_profile_match((u8 *)bssid))
return -1;
#endif
return 0;
}
@ -2310,6 +2394,11 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
memcpy(sm->pmk, esp_wifi_sta_get_ap_info_prof_pmk_internal(), PMK_LEN);
sm->pmk_len = PMK_LEN;
}
#ifdef CONFIG_IEEE80211R
/* Set XXKey to be PSK for FT key derivation */
sm->xxkey_len = PMK_LEN;
os_memcpy(sm->xxkey, sm->pmk, PMK_LEN);
#endif /* CONFIG_IEEE80211R */
}
void
@ -2328,8 +2417,7 @@ set_assoc_ie(u8 * assoc_buf)
sm->config_assoc_ie(sm->proto, assoc_buf, sm->assoc_wpa_ie_len);
}
static int
wpa_sm_set_key(struct install_key *key_sm, enum wpa_alg alg,
int wpa_sm_set_key(struct install_key *key_sm, enum wpa_alg alg,
u8 *addr, int key_idx, int set_tx,
u8 *seq, size_t seq_len,
u8 *key, size_t key_len,

View File

@ -1,15 +1,9 @@
/*
* wpa_supplicant - WPA definitions
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_H
@ -24,12 +18,11 @@
#include "esp_wifi_crypto_types.h"
#include "wpa_i.h"
struct wpa_sm;
#define WPA_SM_STATE(_sm) ((_sm)->wpa_state)
struct wpa_sm;
int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
bool wpa_sta_is_cur_pmksa_set(void);
bool wpa_sta_in_4way_handshake(void);
bool wpa_sta_cur_pmksa_matches_akm(void);
@ -42,87 +35,11 @@ struct l2_ethhdr {
be16 h_proto;
} STRUCT_PACKED;
/**
* set_key - Configure encryption key
* @ifname: Interface name (for multi-SSID/VLAN support)
* @priv: private driver interface data
* @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
* %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK);
* %WPA_ALG_NONE clears the key.
* @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
* broadcast/default keys
* @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for
* IGTK
* @set_tx: configure this key as the default Tx key (only used when
* driver does not support separate unicast/individual key
* @seq: sequence number/packet number, seq_len octets, the next
* packet number to be used for in replay protection; configured
* for Rx keys (in most cases, this is only used with broadcast
* keys and set to zero for unicast keys)
* @seq_len: length of the seq, depends on the algorithm:
* TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets
* @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
* 8-byte Rx Mic Key
* @key_len: length of the key buffer in octets (WEP: 5 or 13,
* TKIP: 32, CCMP: 16, IGTK: 16)
*
* Returns: 0 on success, -1 on failure
*
* Configure the given key for the kernel driver. If the driver
* supports separate individual keys (4 default keys + 1 individual),
* addr can be used to determine whether the key is default or
* individual. If only 4 keys are supported, the default key with key
* index 0 is used as the individual key. STA must be configured to use
* it as the default Tx key (set_tx is set) and accept Rx for all the
* key indexes. In most cases, WPA uses only key indexes 1 and 2 for
* broadcast keys, so key index 0 is available for this kind of
* configuration.
*
* Please note that TKIP keys include separate TX and RX MIC keys and
* some drivers may expect them in different order than wpa_supplicant
* is using. If the TX/RX keys are swapped, all TKIP encrypted packets
* will tricker Michael MIC errors. This can be fixed by changing the
* order of MIC keys by swapping te bytes 16..23 and 24..31 of the key
* in driver_*.c set_key() implementation, see driver_ndis.c for an
* example on how this can be done.
*/
/**
* send_eapol - Optional function for sending EAPOL packets
* @priv: private driver interface data
* @dest: Destination MAC address
* @proto: Ethertype
* @data: EAPOL packet starting with IEEE 802.1X header
* @data_len: Size of the EAPOL packet
*
* Returns: 0 on success, -1 on failure
*
* This optional function can be used to override l2_packet operations
* with driver specific functionality. If this function pointer is set,
* l2_packet module is not used at all and the driver interface code is
* responsible for receiving and sending all EAPOL packets. The
* received EAPOL packets are sent to core code with EVENT_EAPOL_RX
* event. The driver interface is required to implement get_mac_addr()
* handler if send_eapol() is used.
*/
#define KEYENTRY_TABLE_MAP(key_entry_valid) ((key_entry_valid)%5)
void pp_michael_mic_failure(u16 isunicast);
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, const u8 *pmkid, bool cache_pmksa);
int wpa_hook_init(void);
bool wpa_hook_deinit(void);
char * dup_binstr(const void *src, size_t len);
int wpa_michael_mic_failure(u16 isunicast);
wifi_cipher_type_t cipher_type_map_supp_to_public(unsigned cipher);
@ -131,4 +48,71 @@ unsigned cipher_type_map_public_to_supp(wifi_cipher_type_t cipher);
void wpa_sta_clear_curr_pmksa(void);
int wpa_sm_set_key(struct install_key *sm, enum wpa_alg alg,
u8 *addr, int key_idx, int set_tx,
u8 *seq, size_t seq_len,
u8 *key, size_t key_len,
enum key_flag key_flag);
#ifdef CONFIG_IEEE80211R
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len);
int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie);
int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len,
const u8 *mdie);
const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm);
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len);
int wpa_ft_is_completed(struct wpa_sm *sm);
void wpa_reset_ft_completed(struct wpa_sm *sm);
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr);
int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
const u8 *mdie);
#else /* CONFIG_IEEE80211R */
static inline int
wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
{
return 0;
}
static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm,
const u8 *mdie)
{
return 0;
}
static inline int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len,
const u8 *mdie)
{
return 0;
}
static inline int
wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap)
{
return 0;
}
static inline int wpa_ft_is_completed(struct wpa_sm *sm)
{
return 0;
}
static inline void wpa_reset_ft_completed(struct wpa_sm *sm)
{
}
static inline int
wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
const u8 *src_addr)
{
return -1;
}
#endif /* CONFIG_IEEE80211R */
#endif /* WPA_H */

View File

@ -0,0 +1,900 @@
/*
* WPA Supplicant - IEEE 802.11r - Fast BSS Transition
* Copyright (c) 2006-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/aes_wrap.h"
#include "crypto/random.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wpa.h"
#include "wpa_i.h"
#ifdef CONFIG_IEEE80211R
#define DEFAULT_KEK_LEN 16
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
{
u8 ptk_name[WPA_PMK_NAME_LEN];
const u8 *anonce = key->key_nonce;
if (sm->xxkey_len == 0) {
wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
"derivation");
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "FT: xxkey", sm->xxkey, sm->xxkey_len);
wpa_hexdump_key(MSG_DEBUG, "FT: ssid", sm->ssid, sm->ssid_len);
wpa_hexdump_key(MSG_DEBUG, "FT: r0kh_id", sm->r0kh_id, sm->r0kh_id_len);
wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid,
sm->ssid_len, sm->mobility_domain,
sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
sm->pmk_r0, sm->pmk_r0_name);
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
sm->pmk_r0_name, WPA_PMK_NAME_LEN);
wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
WPA_PMK_NAME_LEN);
return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
sm->bssid, sm->pmk_r1_name, ptk, ptk_name,
sm->key_mgmt, sm->pairwise_cipher);
}
/**
* wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @ies: Association Response IEs or %NULL to clear FT parameters
* @ies_len: Length of ies buffer in octets
* Returns: 0 on success, -1 on failure
*/
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
{
struct wpa_ft_ies ft;
if (sm == NULL)
return 0;
if (!get_ie(ies, ies_len, WLAN_EID_MOBILITY_DOMAIN)) {
os_free(sm->assoc_resp_ies);
sm->assoc_resp_ies = NULL;
sm->assoc_resp_ies_len = 0;
os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN);
os_memset(sm->r0kh_id, 0, FT_R0KH_ID_MAX_LEN);
sm->r0kh_id_len = 0;
os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);
sm->ft_protocol = 0;
return 0;
}
if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
return -1;
if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
return -1;
wpa_hexdump(MSG_DEBUG, "FT: Mobility domain",
ft.mdie, MOBILITY_DOMAIN_ID_LEN);
os_memcpy(sm->mobility_domain, ft.mdie, MOBILITY_DOMAIN_ID_LEN);
sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN];
wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x",
sm->mdie_ft_capab);
if (ft.r0kh_id) {
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID",
ft.r0kh_id, ft.r0kh_id_len);
os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len);
sm->r0kh_id_len = ft.r0kh_id_len;
} else {
/* FIX: When should R0KH-ID be cleared? We need to keep the
* old R0KH-ID in order to be able to use this during FT. */
/*
* os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN);
* sm->r0kh_id_len = 0;
*/
}
if (ft.r1kh_id) {
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID",
ft.r1kh_id, FT_R1KH_ID_LEN);
os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN);
} else
os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);
os_free(sm->assoc_resp_ies);
sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2);
if (sm->assoc_resp_ies) {
u8 *pos = sm->assoc_resp_ies;
os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2);
pos += ft.mdie_len + 2;
if (ft.ftie) {
os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2);
pos += ft.ftie_len + 2;
}
sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies;
wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from "
"(Re)Association Response",
sm->assoc_resp_ies, sm->assoc_resp_ies_len);
}
return 0;
}
/**
* wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @len: Buffer for returning the length of the IEs
* @anonce: ANonce or %NULL if not yet available
* @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
* @kck: 128-bit KCK for MIC or %NULL if no MIC is used
* @kck_len: KCK length in octet
* @target_ap: Target AP address
* @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
* @ric_ies_len: Length of ric_ies buffer in octets
* @ap_mdie: Mobility Domain IE from the target AP
* Returns: Pointer to buffer with IEs or %NULL on failure
*
* Caller is responsible for freeing the returned buffer with os_free();
*/
static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
const u8 *anonce, const u8 *pmk_name,
const u8 *kck, size_t kck_len,
const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len,
const u8 *ap_mdie)
{
size_t buf_len;
u8 *buf, *pos, *ftie_len, *ftie_pos;
struct rsn_mdie *mdie;
struct rsn_ftie *ftie;
struct rsn_ie_hdr *rsnie;
int mdie_len;
u16 capab;
sm->ft_completed = 0;
buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
2 + sm->r0kh_id_len + ric_ies_len + 100;
buf = os_zalloc(buf_len);
if (buf == NULL)
return NULL;
pos = buf;
/* RSNIE[PMKR0Name/PMKR1Name] */
rsnie = (struct rsn_ie_hdr *) pos;
rsnie->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(rsnie->version, RSN_VERSION);
pos = (u8 *) (rsnie + 1);
/* Group Suite Selector */
if (sm->group_cipher != WPA_CIPHER_CCMP &&
sm->group_cipher != WPA_CIPHER_GCMP &&
sm->group_cipher != WPA_CIPHER_TKIP) {
wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
sm->group_cipher);
os_free(buf);
return NULL;
}
RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
sm->group_cipher));
pos += RSN_SELECTOR_LEN;
/* Pairwise Suite Count */
WPA_PUT_LE16(pos, 1);
pos += 2;
/* Pairwise Suite List */
if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
sm->pairwise_cipher);
os_free(buf);
return NULL;
}
RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
sm->pairwise_cipher));
pos += RSN_SELECTOR_LEN;
/* Authenticated Key Management Suite Count */
WPA_PUT_LE16(pos, 1);
pos += 2;
/* Authenticated Key Management Suite List */
if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
else {
wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
sm->key_mgmt);
os_free(buf);
return NULL;
}
pos += RSN_SELECTOR_LEN;
/* RSN Capabilities */
capab = 0;
#ifdef CONFIG_IEEE80211W
if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
capab |= WPA_CAPABILITY_MFPC;
#endif /* CONFIG_IEEE80211W */
WPA_PUT_LE16(pos, capab);
pos += 2;
/* PMKID Count */
WPA_PUT_LE16(pos, 1);
pos += 2;
/* PMKID List [PMKR0Name/PMKR1Name] */
os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN);
pos += WPA_PMK_NAME_LEN;
#ifdef CONFIG_IEEE80211W
if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
/* Management Group Cipher Suite */
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
pos += RSN_SELECTOR_LEN;
}
#endif /* CONFIG_IEEE80211W */
rsnie->len = (pos - (u8 *) rsnie) - 2;
/* MDIE */
mdie_len = wpa_ft_add_mdie(sm, pos, buf_len - (pos - buf), ap_mdie);
if (mdie_len <= 0) {
os_free(buf);
return NULL;
}
mdie = (struct rsn_mdie *) (pos + 2);
pos += mdie_len;
/* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
ftie_pos = pos;
*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
ftie_len = pos++;
ftie = (struct rsn_ftie *) pos;
pos += sizeof(*ftie);
os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
if (anonce)
os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
if (kck) {
/* R1KH-ID sub-element in third FT message */
*pos++ = FTIE_SUBELEM_R1KH_ID;
*pos++ = FT_R1KH_ID_LEN;
os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN);
pos += FT_R1KH_ID_LEN;
}
/* R0KH-ID sub-element */
*pos++ = FTIE_SUBELEM_R0KH_ID;
*pos++ = sm->r0kh_id_len;
os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len);
pos += sm->r0kh_id_len;
*ftie_len = pos - ftie_len - 1;
if (ric_ies) {
/* RIC Request */
os_memcpy(pos, ric_ies, ric_ies_len);
pos += ric_ies_len;
}
if (kck) {
/*
* IEEE Std 802.11r-2008, 11A.8.4
* MIC shall be calculated over:
* non-AP STA MAC address
* Target AP MAC address
* Transaction seq number (5 for ReassocReq, 3 otherwise)
* RSN IE
* MDIE
* FTIE (with MIC field set to 0)
* RIC-Request (if present)
*/
/* Information element count */
ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
ric_ies_len);
if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5,
((u8 *) mdie) - 2, 2 + sizeof(*mdie),
ftie_pos, 2 + *ftie_len,
(u8 *) rsnie, 2 + rsnie->len, ric_ies,
ric_ies_len, ftie->mic) < 0) {
wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
os_free(buf);
return NULL;
}
}
*len = pos - buf;
return buf;
}
static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
{
int keylen;
enum wpa_alg alg;
u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };
wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d",
sm->pairwise_cipher);
return -1;
}
alg = wpa_cipher_to_alg(sm->pairwise_cipher);
keylen = wpa_cipher_key_len(sm->pairwise_cipher);
if (wpa_sm_set_key(&(sm->install_ptk), alg, (u8 *)bssid, 0, 1, null_rsc,
sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen, KEY_FLAG_PAIRWISE) < 0) {
wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
return -1;
}
return 0;
}
/**
* wpa_ft_prepare_auth_request - Generate over-the-air auth request
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @mdie: Target AP MDIE
* Returns: 0 on success, -1 on failure
*/
int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
{
u8 *ft_ies;
size_t ft_ies_len;
/* Generate a new SNonce */
if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
NULL, 0, sm->bssid, NULL, 0, mdie);
if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len, true);
os_free(ft_ies);
}
return 0;
}
int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *buf, size_t buf_len,
const u8 *ap_mdie)
{
u8 *pos = buf;
struct rsn_mdie *mdie;
if (buf_len < 2 + sizeof(*mdie)) {
wpa_printf(MSG_INFO,
"FT: Failed to add MDIE: short buffer, length=%zu",
buf_len);
return 0;
}
*pos++ = WLAN_EID_MOBILITY_DOMAIN;
*pos++ = sizeof(*mdie);
mdie = (struct rsn_mdie *) pos;
os_memcpy(mdie->mobility_domain, sm->mobility_domain,
MOBILITY_DOMAIN_ID_LEN);
mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
sm->mdie_ft_capab;
return 2 + sizeof(*mdie);
}
const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm)
{
return sm->mobility_domain;
}
int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
int ft_action, const u8 *target_ap,
const u8 *ric_ies, size_t ric_ies_len)
{
u8 *ft_ies;
size_t ft_ies_len;
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
struct rsn_ftie *ftie;
u8 ptk_name[WPA_PMK_NAME_LEN];
int ret;
const u8 *bssid;
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
if (ft_action) {
if (!sm->over_the_ds_in_progress) {
wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
"- drop FT Action Response");
return -1;
}
if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress "
"with this Target AP - drop FT Action "
"Response");
return -1;
}
}
if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
}
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
}
mdie = (struct rsn_mdie *) parse.mdie;
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
os_memcmp(mdie->mobility_domain, sm->mobility_domain,
MOBILITY_DOMAIN_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
return -1;
}
ftie = (struct rsn_ftie *) parse.ftie;
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
return -1;
}
if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
ftie->snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->snonce, WPA_NONCE_LEN);
return -1;
}
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
return -1;
}
if (parse.r0kh_id_len != sm->r0kh_id_len ||
os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
{
wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
"the current R0KH-ID");
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
parse.r0kh_id, parse.r0kh_id_len);
wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
sm->r0kh_id, sm->r0kh_id_len);
return -1;
}
if (parse.r1kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
return -1;
}
if (parse.rsn_pmkid == NULL ||
os_memcmp_const(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN))
{
wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in "
"RSNIE");
return -1;
}
os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
bssid = target_ap;
if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce,
sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk,
ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0)
return -1;
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
sm->pmk_r1_name,
sm->ptk.kck, sm->ptk.kck_len, bssid,
ric_ies, ric_ies_len,
parse.mdie ? parse.mdie - 2 : NULL);
if (ft_ies) {
wpa_sm_update_ft_ies(sm, sm->mobility_domain,
ft_ies, ft_ies_len, false);
os_free(ft_ies);
}
wpa_sm_mark_authenticated(sm, bssid);
ret = wpa_ft_install_ptk(sm, bssid);
if (ret) {
/*
* Some drivers do not support key configuration when we are
* not associated with the target AP. Work around this by
* trying again after the following reassociation gets
* completed.
*/
wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to "
"association - try again after reassociation");
sm->set_ptk_after_assoc = 1;
} else
sm->set_ptk_after_assoc = 0;
sm->ft_completed = 1;
if (ft_action) {
/*
* The caller is expected trigger re-association with the
* Target AP.
*/
os_memcpy(sm->bssid, target_ap, ETH_ALEN);
}
return 0;
}
int wpa_ft_is_completed(struct wpa_sm *sm)
{
if (sm == NULL)
return 0;
if (!wpa_key_mgmt_ft(sm->key_mgmt))
return 0;
return sm->ft_completed;
}
void wpa_reset_ft_completed(struct wpa_sm *sm)
{
if (sm != NULL)
sm->ft_completed = 0;
}
static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
size_t gtk_elem_len)
{
u8 gtk[32];
int keyidx;
enum wpa_alg alg;
size_t gtk_len, keylen, rsc_len;
if (gtk_elem == NULL) {
wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE");
return 0;
}
wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
gtk_elem, gtk_elem_len);
if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 ||
gtk_elem_len - 19 > sizeof(gtk)) {
wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
"length %lu", (unsigned long) gtk_elem_len);
return -1;
}
gtk_len = gtk_elem_len - 19;
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11, gtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt GTK");
return -1;
}
keylen = wpa_cipher_key_len(sm->group_cipher);
rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
alg = wpa_cipher_to_alg(sm->group_cipher);
if (alg == WIFI_WPA_ALG_NONE) {
wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
sm->group_cipher);
return -1;
}
if (gtk_len < keylen) {
wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
return -1;
}
/* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */
keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
if (gtk_elem[2] != keylen) {
wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
"negotiated %lu",
gtk_elem[2], (unsigned long) keylen);
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
if (sm->group_cipher == WPA_CIPHER_TKIP) {
/* Swap Tx/Rx keys for Michael MIC */
u8 tmp[8];
os_memcpy(tmp, gtk + 16, 8);
os_memcpy(gtk + 16, gtk + 24, 8);
os_memcpy(gtk + 24, tmp, 8);
}
if (wpa_sm_set_key(&(sm->install_gtk), alg, sm->bssid, keyidx, 0,
(u8 *)(gtk_elem + 3), rsc_len, gtk, keylen, KEY_FLAG_GROUP | KEY_FLAG_RX) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
"driver.");
return -1;
}
return 0;
}
#ifdef CONFIG_IEEE80211W
static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
size_t igtk_elem_len)
{
u8 igtk[WPA_IGTK_LEN];
if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
return 0;
if (igtk_elem == NULL) {
wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE");
return 0;
}
wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
igtk_elem, igtk_elem_len);
if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) {
wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
"length %lu", (unsigned long) igtk_elem_len);
return -1;
}
if (igtk_elem[8] != WPA_IGTK_LEN) {
wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
"%d", igtk_elem[8]);
return -1;
}
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8,
igtk_elem + 9, igtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt IGTK");
return -1;
}
/* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */
wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
WPA_IGTK_LEN);
#ifdef ESP_SUPPLICANT
if (esp_wifi_set_igtk_internal(WIFI_IF_STA, (wifi_wpa_igtk_t *)igtk) < 0) {
#else
keyidx = WPA_GET_LE16(igtk_elem);
if (wpa_sm_set_key(&(sm->install_gtk), WIFI_WPA_ALG_IGTK, sm->bssid, keyidx, 0,
(u8 *)(igtk_elem + 2), 6, igtk, WPA_IGTK_LEN, sm->key_entry_valid) < 0) {
#endif
wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
"driver.");
return -1;
}
return 0;
}
#endif /* CONFIG_IEEE80211W */
int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
size_t ies_len, const u8 *src_addr)
{
struct wpa_ft_ies parse;
struct rsn_mdie *mdie;
struct rsn_ftie *ftie;
unsigned int count;
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
}
if (sm->ft_reassoc_completed) {
wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission");
return 0;
}
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
}
mdie = (struct rsn_mdie *) parse.mdie;
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
os_memcmp(mdie->mobility_domain, sm->mobility_domain,
MOBILITY_DOMAIN_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
return -1;
}
ftie = (struct rsn_ftie *) parse.ftie;
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
return -1;
}
if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
ftie->snonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
sm->snonce, WPA_NONCE_LEN);
return -1;
}
if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
ftie->anonce, WPA_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
sm->anonce, WPA_NONCE_LEN);
return -1;
}
if (parse.r0kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
return -1;
}
if (parse.r0kh_id_len != sm->r0kh_id_len ||
os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
{
wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
"the current R0KH-ID");
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
parse.r0kh_id, parse.r0kh_id_len);
wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
sm->r0kh_id, sm->r0kh_id_len);
return -1;
}
if (parse.r1kh_id == NULL) {
wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
return -1;
}
if (os_memcmp_const(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
"ReassocResp");
return -1;
}
if (parse.rsn_pmkid == NULL ||
os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
{
wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
"RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
return -1;
}
count = 3;
if (parse.ric)
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
if (ftie->mic_control[1] != count) {
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
"Control: received %u expected %u",
ftie->mic_control[1], count);
return -1;
}
if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6,
parse.mdie - 2, parse.mdie_len + 2,
parse.ftie - 2, parse.ftie_len + 2,
parse.rsn - 2, parse.rsn_len + 2,
parse.ric, parse.ric_len,
mic) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
return -1;
}
if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
return -1;
}
sm->ft_reassoc_completed = 1;
if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
return -1;
#ifdef CONFIG_IEEE80211W
if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0)
return -1;
#endif /* CONFIG_IEEE80211W */
if (sm->set_ptk_after_assoc) {
wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we "
"are associated");
if (wpa_ft_install_ptk(sm, src_addr) < 0)
return -1;
sm->set_ptk_after_assoc = 0;
}
if (parse.ric) {
wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
parse.ric, parse.ric_len);
/* TODO: parse response and inform driver about results when
* using wpa_supplicant SME */
}
wpa_printf(MSG_DEBUG, "FT: Completed successfully");
return 0;
}
/**
* wpa_ft_start_over_ds - Generate over-the-DS auth request
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @target_ap: Target AP Address
* @mdie: Mobility Domain IE from the target AP
* Returns: 0 on success, -1 on failure
*/
int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
const u8 *mdie)
{
u8 *ft_ies;
size_t ft_ies_len;
wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR,
MAC2STR(target_ap));
/* Generate a new SNonce */
if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce");
return -1;
}
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
NULL, 0, target_ap, NULL, 0, mdie);
if (ft_ies) {
sm->over_the_ds_in_progress = 1;
os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len);
os_free(ft_ies);
}
return 0;
}
#endif /* CONFIG_IEEE80211R */

View File

@ -1,20 +1,15 @@
/*
* Internal WPA/RSN supplicant state machine definitions
* Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WPA_I_H
#define WPA_I_H
extern struct wpa_sm gWpaSm;
struct install_key {
int keys_cleared;
enum wpa_alg alg;
@ -31,7 +26,6 @@ struct install_key {
struct wpa_sm {
u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
struct wpa_ptk ptk, tptk;
int ptk_set, tptk_set;
u8 snonce[WPA_NONCE_LEN];
@ -42,6 +36,8 @@ struct wpa_sm {
u8 request_counter[WPA_REPLAY_COUNTER_LEN];
struct rsn_pmksa_cache *pmksa; /* PMKSA cache */
struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */
u8 ssid[32];
size_t ssid_len;
unsigned int pairwise_cipher;
unsigned int group_cipher;
@ -91,6 +87,27 @@ struct wpa_sm {
wifi_pmf_config_t pmf_cfg;
u8 eapol1_count;
struct rsn_sppamsdu_sup spp_sup;
#ifdef CONFIG_IEEE80211R
u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
size_t xxkey_len;
u8 pmk_r0[PMK_LEN];
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
u8 pmk_r1[PMK_LEN];
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0kh_id[FT_R0KH_ID_MAX_LEN];
size_t r0kh_id_len;
u8 r1kh_id[FT_R1KH_ID_LEN];
unsigned int ft_completed:1;
unsigned int ft_reassoc_completed:1;
unsigned int ft_protocol:1;
int over_the_ds_in_progress;
u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
int set_ptk_after_assoc;
u8 mdie_ft_capab; /* FT Capability and Policy from target AP MDIE */
u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */
size_t assoc_resp_ies_len;
#endif /* CONFIG_IEEE80211R */
};
/**
@ -141,6 +158,22 @@ struct wpa_sm {
typedef void (* WPA_SEND_FUNC)(void *buffer, u16 len);
int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
const u8 *ies, size_t ies_len, bool auth_ie);
static inline int wpa_sm_send_ft_action(struct wpa_sm *sm, u8 action,
const u8 *target_ap,
const u8 *ies, size_t ies_len)
{
return -1;
}
static inline int wpa_sm_mark_authenticated(struct wpa_sm *sm,
const u8 *target_ap)
{
return 0;
}
typedef void (* WPA_SET_ASSOC_IE)(u8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len);
typedef void (*WPA_INSTALL_KEY) (enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
@ -152,6 +185,7 @@ typedef void (*WPA_DEAUTH_FUNC)(u8 reason_code);
typedef void (*WPA_NEG_COMPLETE)(void);
bool wpa_sm_init(char * payload, WPA_SEND_FUNC snd_func, \
WPA_SET_ASSOC_IE set_assoc_ie_func, \
WPA_INSTALL_KEY ppinstallkey, \
@ -168,4 +202,7 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode);
int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len);
int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key, struct wpa_ptk *ptk);
#endif /* WPA_I_H */

View File

@ -370,6 +370,8 @@ typedef u64 __bitwise le64;
#endif /* __GNUC__ */
#endif /* __must_check */
#define SSID_MAX_LEN 32
int hwaddr_aton(const char *txt, u8 *addr);
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
int hwaddr_compact_aton(const char *txt, u8 *addr);

View File

@ -383,6 +383,7 @@ static void initialise_wifi(void)
.btm_enabled =1,
.mbo_enabled =1,
.pmf_cfg.capable = 1,
.ft_enabled =1,
},
};

View File

@ -1,3 +1,4 @@
CONFIG_WPA_11KV_SUPPORT=y
CONFIG_WPA_SCAN_CACHE=y
CONFIG_WPA_MBO_SUPPORT=y
CONFIG_WPA_11R_SUPPORT=y

View File

@ -1679,7 +1679,6 @@ components/wpa_supplicant/include/utils/wpabuf.h
components/wpa_supplicant/port/include/byteswap.h
components/wpa_supplicant/port/include/endian.h
components/wpa_supplicant/port/include/os.h
components/wpa_supplicant/port/include/supplicant_opt.h
components/wpa_supplicant/port/os_xtensa.c
components/wpa_supplicant/src/ap/ap_config.c
components/wpa_supplicant/src/ap/ap_config.h