2022-06-16 10:01:02 -04:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2019-11-21 02:11:12 -05:00
|
|
|
|
|
|
|
#ifdef CONFIG_WPA3_SAE
|
|
|
|
|
2019-11-11 06:22:07 -05:00
|
|
|
#include "common/sae.h"
|
2020-01-20 01:47:53 -05:00
|
|
|
#include "common/ieee802_11_defs.h"
|
2019-11-21 02:11:12 -05:00
|
|
|
#include "esp_wifi_driver.h"
|
|
|
|
#include "rsn_supp/wpa.h"
|
|
|
|
|
2022-06-16 10:01:02 -04:00
|
|
|
static struct sae_pt *g_sae_pt;
|
2019-11-21 02:11:12 -05:00
|
|
|
static struct sae_data g_sae_data;
|
2020-01-20 01:47:53 -05:00
|
|
|
static struct wpabuf *g_sae_token = NULL;
|
2020-05-09 07:34:40 -04:00
|
|
|
static struct wpabuf *g_sae_commit = NULL;
|
|
|
|
static struct wpabuf *g_sae_confirm = NULL;
|
2019-11-21 02:11:12 -05:00
|
|
|
int g_allowed_groups[] = { IANA_SECP256R1, 0 };
|
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
static esp_err_t wpa3_build_sae_commit(u8 *bssid)
|
2019-11-21 02:11:12 -05:00
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
int default_group = IANA_SECP256R1;
|
|
|
|
u32 len = 0;
|
|
|
|
u8 own_addr[ETH_ALEN];
|
2022-06-16 10:01:02 -04:00
|
|
|
const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
|
|
|
|
struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
|
|
|
|
uint8_t use_pt = esp_wifi_get_use_h2e_internal();
|
|
|
|
|
|
|
|
if (use_pt && !g_sae_pt) {
|
|
|
|
g_sae_pt = sae_derive_pt(g_allowed_groups, ssid->ssid, ssid->len, pw, strlen((const char *)pw), NULL);
|
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2020-07-08 06:26:05 -04:00
|
|
|
if (wpa_sta_cur_pmksa_matches_akm()) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_sae_commit) {
|
|
|
|
wpabuf_free(g_sae_commit);
|
|
|
|
g_sae_commit = NULL;
|
2020-01-20 01:47:53 -05:00
|
|
|
}
|
|
|
|
|
2020-05-09 07:07:19 -04:00
|
|
|
if (g_sae_token) {
|
|
|
|
len = wpabuf_len(g_sae_token);
|
|
|
|
goto reuse_data;
|
|
|
|
}
|
2020-01-20 01:47:53 -05:00
|
|
|
|
2020-05-09 07:07:19 -04:00
|
|
|
memset(&g_sae_data, 0, sizeof(g_sae_data));
|
|
|
|
if (sae_set_group(&g_sae_data, default_group)) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: could not set SAE group %d", default_group);
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2020-05-09 07:07:19 -04:00
|
|
|
esp_wifi_get_macaddr_internal(WIFI_IF_STA, own_addr);
|
|
|
|
if (!bssid) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: cannot prepare SAE commit with no BSSID!");
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2022-06-16 10:01:02 -04:00
|
|
|
if (use_pt &&
|
|
|
|
sae_prepare_commit_pt(&g_sae_data, g_sae_pt,
|
|
|
|
own_addr, bssid, NULL) < 0) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
if (!use_pt &&
|
|
|
|
sae_prepare_commit(own_addr, bssid, pw,
|
|
|
|
strlen((const char *)pw),
|
|
|
|
&g_sae_data) < 0) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2020-01-20 01:47:53 -05:00
|
|
|
reuse_data:
|
2020-05-09 07:07:19 -04:00
|
|
|
len += SAE_COMMIT_MAX_LEN;
|
2020-05-09 07:34:40 -04:00
|
|
|
g_sae_commit = wpabuf_alloc(len);
|
|
|
|
if (!g_sae_commit) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
if (sae_write_commit(&g_sae_data, g_sae_commit, g_sae_token, NULL) != ESP_OK) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
|
2020-05-09 07:34:40 -04:00
|
|
|
wpabuf_free(g_sae_commit);
|
|
|
|
g_sae_commit = NULL;
|
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (g_sae_token) {
|
|
|
|
wpabuf_free(g_sae_token);
|
|
|
|
g_sae_token = NULL;
|
|
|
|
}
|
|
|
|
g_sae_data.state = SAE_COMMITTED;
|
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_OK;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
static esp_err_t wpa3_build_sae_confirm(void)
|
2019-11-21 02:11:12 -05:00
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
if (g_sae_data.state != SAE_COMMITTED)
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
|
|
|
|
|
|
|
if (g_sae_confirm) {
|
|
|
|
wpabuf_free(g_sae_confirm);
|
|
|
|
g_sae_confirm = NULL;
|
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
g_sae_confirm = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
|
|
|
|
if (!g_sae_confirm) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
2019-11-11 06:22:07 -05:00
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
if (sae_write_confirm(&g_sae_data, g_sae_confirm) != ESP_OK) {
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
|
2020-05-09 07:34:40 -04:00
|
|
|
wpabuf_free(g_sae_confirm);
|
|
|
|
g_sae_confirm = NULL;
|
|
|
|
return ESP_FAIL;
|
2020-05-09 07:07:19 -04:00
|
|
|
}
|
|
|
|
g_sae_data.state = SAE_CONFIRMED;
|
2019-11-21 02:11:12 -05:00
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void esp_wpa3_free_sae_data(void)
|
|
|
|
{
|
|
|
|
if (g_sae_commit) {
|
|
|
|
wpabuf_free(g_sae_commit);
|
|
|
|
g_sae_commit = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_sae_confirm) {
|
|
|
|
wpabuf_free(g_sae_confirm);
|
|
|
|
g_sae_confirm = NULL;
|
|
|
|
}
|
|
|
|
sae_clear_data(&g_sae_data);
|
2022-06-16 10:01:02 -04:00
|
|
|
if (g_sae_pt) {
|
|
|
|
sae_deinit_pt(g_sae_pt);
|
|
|
|
g_sae_pt = NULL;
|
|
|
|
}
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
2020-11-05 23:00:07 -05:00
|
|
|
static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len)
|
2019-11-21 02:11:12 -05:00
|
|
|
{
|
2020-05-09 07:34:40 -04:00
|
|
|
u8 *buf = NULL;
|
2020-05-09 07:07:19 -04:00
|
|
|
|
|
|
|
switch (sae_msg_type) {
|
|
|
|
case SAE_MSG_COMMIT:
|
2020-05-09 07:34:40 -04:00
|
|
|
if (ESP_OK != wpa3_build_sae_commit(bssid))
|
|
|
|
return NULL;
|
2020-11-05 23:00:07 -05:00
|
|
|
*sae_msg_len = wpabuf_len(g_sae_commit);
|
2020-05-09 07:34:40 -04:00
|
|
|
buf = wpabuf_mhead_u8(g_sae_commit);
|
2020-05-09 07:07:19 -04:00
|
|
|
break;
|
|
|
|
case SAE_MSG_CONFIRM:
|
2020-05-09 07:34:40 -04:00
|
|
|
if (ESP_OK != wpa3_build_sae_confirm())
|
|
|
|
return NULL;
|
2020-11-05 23:00:07 -05:00
|
|
|
*sae_msg_len = wpabuf_len(g_sae_confirm);
|
2020-05-09 07:34:40 -04:00
|
|
|
buf = wpabuf_mhead_u8(g_sae_confirm);
|
2020-05-09 07:07:19 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-05-09 07:34:40 -04:00
|
|
|
return buf;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
2020-01-20 01:47:53 -05:00
|
|
|
static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
|
2019-11-21 02:11:12 -05:00
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (g_sae_data.state != SAE_COMMITTED) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
|
|
|
|
g_sae_data.state);
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
|
|
|
|
if (g_sae_token)
|
|
|
|
wpabuf_free(g_sae_token);
|
2022-06-16 10:01:02 -04:00
|
|
|
if (g_sae_data.h2e) {
|
|
|
|
if ((buf[2] != WLAN_EID_EXTENSION) ||
|
|
|
|
(buf[3] == 0) ||
|
|
|
|
(buf[3] > len - 4) ||
|
|
|
|
(buf[4] != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN)) {
|
|
|
|
wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token container header");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
g_sae_token = wpabuf_alloc_copy(buf + 5, len - 5);
|
|
|
|
} else {
|
|
|
|
g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2);
|
|
|
|
}
|
2020-05-09 07:07:19 -04:00
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
2022-06-16 10:01:02 -04:00
|
|
|
ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups,
|
|
|
|
status == WLAN_STATUS_SAE_HASH_TO_ELEMENT);
|
2020-05-09 07:07:19 -04:00
|
|
|
if (ret) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = sae_process_commit(&g_sae_data);
|
|
|
|
if (ret) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ESP_OK;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
|
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
if (g_sae_data.state != SAE_CONFIRMED) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
|
|
|
|
g_sae_data.state);
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sae_check_confirm(&g_sae_data, buf, len) != ESP_OK) {
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE confirm");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
g_sae_data.state = SAE_ACCEPTED;
|
|
|
|
|
|
|
|
wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmkid, true);
|
|
|
|
|
|
|
|
return ESP_OK;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
2020-11-05 23:00:07 -05:00
|
|
|
static int wpa3_parse_sae_msg(u8 *buf, size_t len, u32 sae_msg_type, u16 status)
|
2019-11-21 02:11:12 -05:00
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
int ret = ESP_OK;
|
|
|
|
|
|
|
|
switch (sae_msg_type) {
|
|
|
|
case SAE_MSG_COMMIT:
|
|
|
|
ret = wpa3_parse_sae_commit(buf, len, status);
|
|
|
|
break;
|
|
|
|
case SAE_MSG_CONFIRM:
|
|
|
|
ret = wpa3_parse_sae_confirm(buf, len);
|
2020-05-09 07:34:40 -04:00
|
|
|
esp_wpa3_free_sae_data();
|
2020-05-09 07:07:19 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%d)!", sae_msg_type);
|
|
|
|
ret = ESP_FAIL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void esp_wifi_register_wpa3_cb(struct wpa_funcs *wpa_cb)
|
|
|
|
{
|
2020-05-09 07:07:19 -04:00
|
|
|
wpa_cb->wpa3_build_sae_msg = wpa3_build_sae_msg;
|
|
|
|
wpa_cb->wpa3_parse_sae_msg = wpa3_parse_sae_msg;
|
2019-11-21 02:11:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CONFIG_WPA3_SAE */
|