Merge branch 'bugfix/wpa3_softap_supplicant_coverity_fixes' into 'master'

esp_wifi: Fix some SAE SoftAP issues

Closes WIFI-5493, WIFI-5498, IDF-7028, WIFI-5516, and WIFI-5515

See merge request espressif/esp-idf!22574
This commit is contained in:
Jiang Jiang Jian 2023-03-13 10:33:27 +08:00
commit 3cad41ee77
7 changed files with 57 additions and 75 deletions

View File

@ -224,17 +224,11 @@ bool hostap_deinit(void *data)
esp_wifi_unset_appie_internal(WIFI_APPIE_WPA); esp_wifi_unset_appie_internal(WIFI_APPIE_WPA);
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
uint8_t authmode; wpa3_hostap_auth_deinit();
authmode = esp_wifi_ap_get_prof_authmode_internal(); /* Wait till lock is released by wpa3 task */
if (authmode == WIFI_AUTH_WPA3_PSK || if (g_wpa3_hostap_auth_api_lock &&
authmode == WIFI_AUTH_WPA2_WPA3_PSK) { WPA3_HOSTAP_AUTH_API_LOCK() == pdTRUE) {
wpa3_hostap_auth_deinit(); WPA3_HOSTAP_AUTH_API_UNLOCK();
/* Wait till lock is released by wpa3 task */
if (WPA3_HOSTAP_AUTH_API_LOCK() == pdTRUE) {
WPA3_HOSTAP_AUTH_API_UNLOCK();
os_mutex_delete(g_wpa3_hostap_auth_api_lock);
g_wpa3_hostap_auth_api_lock = NULL;
}
} }
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
@ -259,7 +253,7 @@ int esp_wifi_build_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
} }
flen = (capab & 0xff00) ? 2 : 1; flen = 1;
if (len < 2 + flen || !capab) { if (len < 2 + flen || !capab) {
return 0; /* no supported extended RSN capabilities */ return 0; /* no supported extended RSN capabilities */
} }
@ -268,10 +262,6 @@ int esp_wifi_build_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
*pos++ = WLAN_EID_RSNX; *pos++ = WLAN_EID_RSNX;
*pos++ = flen; *pos++ = flen;
*pos++ = capab & 0x00ff; *pos++ = capab & 0x00ff;
capab >>= 8;
if (capab) {
*pos++ = capab;
}
return pos - eid; return pos - eid;
} }

View File

@ -461,7 +461,7 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt)
} }
os_mutex_unlock(sta->lock); os_mutex_unlock(sta->lock);
if (ret != WLAN_STATUS_SUCCESS) { if (ret != WLAN_STATUS_SUCCESS) {
uint16_t aid = 0; uint16_t aid = -1;
if (esp_wifi_ap_get_sta_aid(frm->bssid, &aid) == ESP_OK && aid == 0) { if (esp_wifi_ap_get_sta_aid(frm->bssid, &aid) == ESP_OK && aid == 0) {
esp_wifi_ap_deauth_internal(frm->bssid, ret); esp_wifi_ap_deauth_internal(frm->bssid, ret);
} }
@ -521,23 +521,23 @@ static void esp_wpa3_hostap_task(void *pvParameters)
int wpa3_hostap_auth_init(void *data) int wpa3_hostap_auth_init(void *data)
{ {
int ret = ESP_OK;
if (g_wpa3_hostap_evt_queue) { if (g_wpa3_hostap_evt_queue) {
wpa_printf(MSG_ERROR, "esp_wpa3_hostap_task has already been initialised"); wpa_printf(MSG_ERROR, "esp_wpa3_hostap_task has already been initialised");
return ret; return ESP_OK;
} }
g_wpa3_hostap_auth_api_lock = os_semphr_create(1, 0); if (g_wpa3_hostap_auth_api_lock == NULL) {
if (!g_wpa3_hostap_auth_api_lock) { g_wpa3_hostap_auth_api_lock = os_semphr_create(1, 1);
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create WPA3 hostap auth API lock"); if (!g_wpa3_hostap_auth_api_lock) {
return ESP_FAIL; wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create WPA3 hostap auth API lock");
return ESP_FAIL;
}
} }
g_wpa3_hostap_evt_queue = os_queue_create(10, sizeof(wpa3_hostap_auth_event_t)); g_wpa3_hostap_evt_queue = os_queue_create(10, sizeof(wpa3_hostap_auth_event_t));
if (!g_wpa3_hostap_evt_queue) { if (!g_wpa3_hostap_evt_queue) {
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create queue"); wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create queue");
ret = ESP_FAIL; return ESP_FAIL;
goto init_done;
} }
if (os_task_create(esp_wpa3_hostap_task, "esp_wpa3_hostap_task", if (os_task_create(esp_wpa3_hostap_task, "esp_wpa3_hostap_task",
@ -546,22 +546,18 @@ int wpa3_hostap_auth_init(void *data)
&g_wpa3_hostap_task_hdl) != pdPASS) { &g_wpa3_hostap_task_hdl) != pdPASS) {
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create task"); wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create task");
os_queue_delete(g_wpa3_hostap_evt_queue); os_queue_delete(g_wpa3_hostap_evt_queue);
ret = ESP_FAIL; return ESP_FAIL;
goto init_done;
} }
struct hostapd_data *hapd = (struct hostapd_data *)data; struct hostapd_data *hapd = (struct hostapd_data *)data;
dl_list_init(&hapd->sae_commit_queue); dl_list_init(&hapd->sae_commit_queue);
return ESP_OK;
init_done:
WPA3_HOSTAP_AUTH_API_UNLOCK();
return ret;
} }
bool wpa3_hostap_auth_deinit(void) bool wpa3_hostap_auth_deinit(void)
{ {
if (wpa3_hostap_post_evt(SIG_TASK_DEL, 0) != 0) { if (wpa3_hostap_post_evt(SIG_TASK_DEL, 0) != 0) {
wpa_printf(MSG_ERROR, "failed to send task delete event"); wpa_printf(MSG_DEBUG, "failed to send task delete event");
return false; return false;
} else { } else {
return true; return true;

View File

@ -202,7 +202,7 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
for (sta = hapd->sta_list; sta; sta = sta->next) { for (sta = hapd->sta_list; sta; sta = sta->next) {
if (sta->sae && if (sta->sae &&
(sta->sae->state == SAE_COMMITTED || (sta->sae->state == SAE_COMMITTED ||
sta->sae->state != SAE_CONFIRMED)) { sta->sae->state == SAE_CONFIRMED)) {
open++; open++;
} }
if (open >= hapd->conf->sae_anti_clogging_threshold) { if (open >= hapd->conf->sae_anti_clogging_threshold) {
@ -358,13 +358,12 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
if (ret) { if (ret) {
return ret; return ret;
} }
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
if (sae_process_commit(sta->sae) < 0) { if (sae_process_commit(sta->sae) < 0) {
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
} }
sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
sta->sae->sync = 0; sta->sae->sync = 0;
} else { } else {
if (sae_check_big_sync(hapd, sta)) { if (sae_check_big_sync(hapd, sta)) {
@ -534,38 +533,36 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
goto remove_sta; goto remove_sta;
} }
if (sta->sae->state >= SAE_CONFIRMED) { const u8 *var;
const u8 *var; size_t var_len;
size_t var_len; u16 peer_send_confirm;
u16 peer_send_confirm;
var = buf; var = buf;
var_len = len; var_len = len;
if (var_len < 2) { if (var_len < 2) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE; resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto reply; goto reply;
} }
peer_send_confirm = WPA_GET_LE16(var); peer_send_confirm = WPA_GET_LE16(var);
if (sta->sae->state == SAE_ACCEPTED && if (sta->sae->state == SAE_ACCEPTED &&
(peer_send_confirm <= sta->sae->rc || (peer_send_confirm <= sta->sae->rc ||
peer_send_confirm == 0xffff)) { peer_send_confirm == 0xffff)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"SAE: Silently ignore unexpected Confirm from peer " "SAE: Silently ignore unexpected Confirm from peer "
MACSTR MACSTR
" (peer-send-confirm=%u Rc=%u)", " (peer-send-confirm=%u Rc=%u)",
MAC2STR(sta->addr), MAC2STR(sta->addr),
peer_send_confirm, sta->sae->rc); peer_send_confirm, sta->sae->rc);
return 0; return 0;
} }
if (sae_check_confirm(sta->sae, buf, len) < 0) { if (sae_check_confirm(sta->sae, buf, len) < 0) {
resp = WLAN_STATUS_UNSPECIFIED_FAILURE; resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto reply; goto reply;
} }
sta->sae->rc = peer_send_confirm; sta->sae->rc = peer_send_confirm;
}
resp = sae_sm_step(hapd, sta, bssid, auth_transaction, resp = sae_sm_step(hapd, sta, bssid, auth_transaction,
status, 0, &sta_removed); status, 0, &sta_removed);

View File

@ -495,7 +495,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
void wpa_auth_sta_deinit(struct wpa_state_machine *sm) void wpa_auth_sta_deinit(struct wpa_state_machine *sm)
{ {
#ifdef ESP_SUPPLICANT #ifdef ESP_SUPPLICANT
if (esp_wifi_ap_is_sta_sae_reauth_node(sm->addr)) { if (sm && esp_wifi_ap_is_sta_sae_reauth_node(sm->addr)) {
wpa_printf( MSG_DEBUG, "deinit old sm=%p\n", sm); wpa_printf( MSG_DEBUG, "deinit old sm=%p\n", sm);
} }
#else /* ESP_SUPPLICANT */ #else /* ESP_SUPPLICANT */
@ -2509,6 +2509,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
} }
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len, uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len,
bool *pmf_enable, int subtype) bool *pmf_enable, int subtype)
@ -2614,6 +2615,7 @@ bool wpa_ap_remove(void* sta_info)
return true; return true;
} }
#endif /* CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr) const u8 *sta_addr)

View File

@ -311,7 +311,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
} }
flen = (capab & 0xff00) ? 2 : 1; flen = 1;
if (!capab) if (!capab)
return 0; /* no supported extended RSN capabilities */ return 0; /* no supported extended RSN capabilities */
if (len < 2 + flen) if (len < 2 + flen)
@ -321,9 +321,6 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
*pos++ = WLAN_EID_RSNX; *pos++ = WLAN_EID_RSNX;
*pos++ = flen; *pos++ = flen;
*pos++ = capab & 0x00ff; *pos++ = capab & 0x00ff;
capab >>= 8;
if (capab)
*pos++ = capab;
return pos - buf; return pos - buf;
} }

View File

@ -2212,10 +2212,10 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
return ESP_FAIL; return ESP_FAIL;
/* Send-Confirm */ /* Send-Confirm */
if (sae->send_confirm < 0xffff)
sae->send_confirm++;
sc = wpabuf_put(buf, 0); sc = wpabuf_put(buf, 0);
wpabuf_put_le16(buf, sae->send_confirm); wpabuf_put_le16(buf, sae->send_confirm);
if (sae->send_confirm < 0xffff)
sae->send_confirm++;
if (sae->tmp->ec) { if (sae->tmp->ec) {
if (sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, if (sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,

View File

@ -493,17 +493,17 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
} }
if (left >= 2) { if (left >= 2) {
data->num_pmkid = WPA_GET_LE16(pos); u16 num_pmkid = WPA_GET_LE16(pos);
pos += 2; pos += 2;
left -= 2; left -= 2;
if (left < (int) data->num_pmkid * PMKID_LEN) { if (num_pmkid > (unsigned int) left / PMKID_LEN) {
wpa_printf(MSG_DEBUG, "%s: PMKID underflow " wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
"(num_pmkid=%lu left=%d)", "(num_pmkid=%u left=%d)",
__func__, (unsigned long) data->num_pmkid, __func__, num_pmkid, left);
left);
data->num_pmkid = 0; data->num_pmkid = 0;
return -9; return -9;
} else { } else {
data->num_pmkid = num_pmkid;
data->pmkid = pos; data->pmkid = pos;
pos += data->num_pmkid * PMKID_LEN; pos += data->num_pmkid * PMKID_LEN;
left -= data->num_pmkid * PMKID_LEN; left -= data->num_pmkid * PMKID_LEN;