mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
wpa_supplicant: Add support for FT psk
This commit is contained in:
parent
baa5b8ed7d
commit
3d5ca7ee6e
@ -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) */
|
||||
|
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define BSS_H
|
||||
|
||||
struct wpa_scan_res;
|
||||
struct wpa_supplicant;
|
||||
|
||||
/**
|
||||
* struct wpa_bss - BSS table
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
900
components/wpa_supplicant/src/rsn_supp/wpa_ft.c
Normal file
900
components/wpa_supplicant/src/rsn_supp/wpa_ft.c
Normal 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 */
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -383,6 +383,7 @@ static void initialise_wifi(void)
|
||||
.btm_enabled =1,
|
||||
.mbo_enabled =1,
|
||||
.pmf_cfg.capable = 1,
|
||||
.ft_enabled =1,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
CONFIG_WPA_11KV_SUPPORT=y
|
||||
CONFIG_WPA_SCAN_CACHE=y
|
||||
CONFIG_WPA_MBO_SUPPORT=y
|
||||
CONFIG_WPA_11R_SUPPORT=y
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user