wpa_supplicant: Support WPA3 4-way handshake, add config option

1. Add changes in 4-way handshake path to allow SAE key mgmt.
2. Support for configuring WAP3 at init time, added Kconfig option.
3. Handle and propagate error conditions properly.
This commit is contained in:
Nachiket Kukade 2020-04-29 18:47:23 +05:30
parent 6b76228fcb
commit d36663b798
13 changed files with 210 additions and 118 deletions

View file

@ -295,6 +295,14 @@ menu "Wi-Fi"
When this option is disabled, more than 17Kbytes of IRAM memory will be saved
but Wi-Fi performance will be reduced.
config ESP32_WIFI_ENABLE_WPA3_SAE
bool "Enable WPA3-Personal"
default n
help
Select this option to allow the device to establish a WPA3-Personal connection with eligible AP's.
PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details.
endmenu # Wi-Fi
menu "PHY"

View file

@ -110,6 +110,7 @@ typedef struct {
int wifi_task_core_id; /**< WiFi Task Core ID */
int beacon_max_len; /**< WiFi softAP maximum length of the beacon */
int mgmt_sbuf_num; /**< WiFi management short buffer number, the minimum value is 6, the maximum value is 32 */
uint64_t feature_caps; /**< Enables additional WiFi features and capabilities */
int magic; /**< WiFi init magic number, it should be the last field */
} wifi_init_config_t;
@ -156,6 +157,7 @@ typedef struct {
#endif
extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
extern uint64_t g_wifi_feature_caps;
#define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F
@ -189,6 +191,8 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
#define WIFI_MGMT_SBUF_NUM 32
#endif
#define CONFIG_FEATURE_WPA3_SAE_BIT (1<<0)
#define WIFI_INIT_CONFIG_DEFAULT() { \
.event_handler = &esp_event_send, \
.osi_funcs = &g_wifi_osi_funcs, \
@ -208,6 +212,7 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
.wifi_task_core_id = WIFI_TASK_CORE_ID,\
.beacon_max_len = WIFI_SOFTAP_BEACON_MAX_LEN, \
.mgmt_sbuf_num = WIFI_MGMT_SBUF_NUM, \
.feature_caps = g_wifi_feature_caps, \
.magic = WIFI_INIT_CONFIG_MAGIC\
};

View file

@ -37,6 +37,13 @@ static esp_pm_lock_handle_t s_wifi_modem_sleep_lock;
/* Callback function to update WiFi MAC time */
wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb = NULL;
/* Set additional WiFi features and capabilities */
uint64_t g_wifi_feature_caps =
#if CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE
CONFIG_FEATURE_WPA3_SAE_BIT |
#endif
0;
static const char* TAG = "wifi_init";
static void __attribute__((constructor)) s_set_default_wifi_log_level()

View file

@ -2,4 +2,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
COMPONENT_PRIV_INCLUDEDIRS := src
COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps
CFLAGS += -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
CFLAGS += -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing

View file

@ -50,6 +50,7 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
@ -82,6 +83,7 @@ static inline int wpa_key_mgmt_sha256(int akm)
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_IEEE8021X_SUITE_B));
}

View file

@ -42,7 +42,7 @@ int sae_set_group(struct sae_data *sae, int group)
sae_clear_data(sae);
tmp = sae->tmp = os_zalloc(sizeof(*tmp));
if (tmp == NULL)
return -1;
return ESP_FAIL;
/* First, check if this is an ECC group */
tmp->ec = crypto_ec_init(group);
@ -53,7 +53,7 @@ int sae_set_group(struct sae_data *sae, int group)
tmp->prime_len = crypto_ec_prime_len(tmp->ec);
tmp->prime = crypto_ec_get_prime(tmp->ec);
tmp->order = crypto_ec_get_order(tmp->ec);
return 0;
return ESP_OK;
}
/* Not an ECC group, check FFC */
@ -65,14 +65,14 @@ int sae_set_group(struct sae_data *sae, int group)
tmp->prime_len = tmp->dh->prime_len;
if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
sae_clear_data(sae);
return -1;
return ESP_FAIL;
}
tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
tmp->prime_len);
if (tmp->prime_buf == NULL) {
sae_clear_data(sae);
return -1;
return ESP_FAIL;
}
tmp->prime = tmp->prime_buf;
@ -80,17 +80,17 @@ int sae_set_group(struct sae_data *sae, int group)
tmp->dh->order_len);
if (tmp->order_buf == NULL) {
sae_clear_data(sae);
return -1;
return ESP_FAIL;
}
tmp->order = tmp->order_buf;
return 0;
return ESP_OK;
}
/* Unsupported group */
wpa_printf(MSG_DEBUG,
"SAE: Group %d not supported by the crypto library", group);
return -1;
return ESP_FAIL;
}
void sae_clear_temp_data(struct sae_data *sae)
@ -236,7 +236,7 @@ static int is_quadratic_residue_blind(struct sae_data *sae,
*/
r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd);
if (!r)
return -1;
return ESP_FAIL;
num = crypto_bignum_init();
if (!num ||
@ -293,22 +293,22 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
bits = crypto_ec_prime_len_bits(sae->tmp->ec);
if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
prime, sae->tmp->prime_len, pwd_value, bits) < 0)
return -1;
return ESP_FAIL;
if (bits % 8)
buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
pwd_value, sae->tmp->prime_len);
if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
return 0;
return ESP_OK;
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
if (!x_cand)
return -1;
return ESP_FAIL;
y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
if (!y_sqr) {
crypto_bignum_deinit(x_cand, 1);
return -1;
return ESP_FAIL;
}
res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
@ -337,14 +337,14 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
bits) < 0)
return -1;
return ESP_FAIL;
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
sae->tmp->prime_len);
if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
{
wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
return 0;
return ESP_OK;
}
/* PWE = pwd-value^((p-1)/r) modulo p */
@ -380,13 +380,13 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
if (res < 0) {
wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
return -1;
return ESP_FAIL;
}
/* if (PWE > 1) --> found */
if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
return 0;
return ESP_OK;
}
wpa_printf(MSG_DEBUG, "SAE: PWE found");
@ -450,12 +450,12 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
if (dummy_password_len > sizeof(dummy_password))
dummy_password_len = sizeof(dummy_password);
if (random_get_bytes(dummy_password, dummy_password_len) < 0)
return -1;
return ESP_FAIL;
prime_len = sae->tmp->prime_len;
if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
prime_len) < 0)
return -1;
return ESP_FAIL;
bits = crypto_ec_prime_len_bits(sae->tmp->ec);
/*
@ -464,7 +464,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
*/
if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
&qr, &qnr) < 0)
return -1;
return ESP_FAIL;
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
password, password_len);
@ -579,7 +579,7 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
if (sae->tmp->pwe_ffc == NULL) {
sae->tmp->pwe_ffc = crypto_bignum_init();
if (sae->tmp->pwe_ffc == NULL)
return -1;
return ESP_FAIL;
}
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
@ -638,7 +638,7 @@ static int sae_derive_commit_element_ecc(struct sae_data *sae,
sae->tmp->own_commit_element_ecc =
crypto_ec_point_init(sae->tmp->ec);
if (!sae->tmp->own_commit_element_ecc)
return -1;
return ESP_FAIL;
}
if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
@ -646,10 +646,10 @@ static int sae_derive_commit_element_ecc(struct sae_data *sae,
crypto_ec_point_invert(sae->tmp->ec,
sae->tmp->own_commit_element_ecc) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
return -1;
return ESP_FAIL;
}
return 0;
return ESP_OK;
}
static int sae_derive_commit_element_ffc(struct sae_data *sae,
@ -659,7 +659,7 @@ static int sae_derive_commit_element_ffc(struct sae_data *sae,
if (!sae->tmp->own_commit_element_ffc) {
sae->tmp->own_commit_element_ffc = crypto_bignum_init();
if (!sae->tmp->own_commit_element_ffc)
return -1;
return ESP_FAIL;
}
if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
@ -668,10 +668,10 @@ static int sae_derive_commit_element_ffc(struct sae_data *sae,
sae->tmp->prime,
sae->tmp->own_commit_element_ffc) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
return -1;
return ESP_FAIL;
}
return 0;
return ESP_OK;
}
static int sae_derive_commit(struct sae_data *sae)
@ -689,13 +689,13 @@ static int sae_derive_commit(struct sae_data *sae)
* theoretical infinite loop, break out after 100
* attemps.
*/
return -1;
return ESP_FAIL;
}
mask = sae_get_rand_and_mask(sae);
if (mask == NULL) {
wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
return -1;
return ESP_FAIL;
}
/* commit-scalar = (rand + mask) modulo r */
@ -733,8 +733,8 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
password_len,
identifier) < 0) ||
sae_derive_commit(sae) < 0)
return -1;
return 0;
return ESP_FAIL;
return ESP_OK;
}
static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
@ -861,17 +861,17 @@ int sae_process_commit(struct sae_data *sae)
(sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
(sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
sae_derive_keys(sae, k) < 0)
return -1;
return 0;
return ESP_FAIL;
return ESP_OK;
}
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
const struct wpabuf *token, const char *identifier)
{
u8 *pos;
if (sae->tmp == NULL)
return;
return ESP_FAIL;
wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
if (token) {
@ -880,23 +880,32 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
wpabuf_head(token), wpabuf_len(token));
}
pos = wpabuf_put(buf, sae->tmp->prime_len);
crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
sae->tmp->prime_len, sae->tmp->prime_len);
if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
sae->tmp->prime_len, sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum operation on own commit scalar");
return ESP_FAIL;
}
wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
pos, sae->tmp->prime_len);
if (sae->tmp->ec) {
pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
crypto_ec_point_to_bin(sae->tmp->ec,
sae->tmp->own_commit_element_ecc,
pos, pos + sae->tmp->prime_len);
if (crypto_ec_point_to_bin(sae->tmp->ec,
sae->tmp->own_commit_element_ecc,
pos, pos + sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
return ESP_FAIL;
}
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
pos, sae->tmp->prime_len);
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
pos + sae->tmp->prime_len, sae->tmp->prime_len);
} else {
pos = wpabuf_put(buf, sae->tmp->prime_len);
crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
sae->tmp->prime_len, sae->tmp->prime_len);
if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
sae->tmp->prime_len, sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum operation on commit elem ffc");
return ESP_FAIL;
}
wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
pos, sae->tmp->prime_len);
}
@ -910,6 +919,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s",
identifier);
}
return ESP_OK;
}
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
@ -1299,7 +1309,7 @@ static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
confirm);
}
static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
const struct crypto_bignum *scalar1,
const struct crypto_ec_point *element1,
const struct crypto_bignum *scalar2,
@ -1309,40 +1319,54 @@ static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
element_b1 + sae->tmp->prime_len);
crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
element_b2 + sae->tmp->prime_len);
if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
element_b1 + sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
return ESP_FAIL;
}
if (crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
element_b2 + sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum op while deriving ec point");
return ESP_FAIL;
}
sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
return ESP_OK;
}
static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
const struct crypto_bignum *scalar1,
const struct crypto_bignum *element1,
const struct crypto_bignum *scalar2,
const struct crypto_bignum *element2,
u8 *confirm)
static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
const struct crypto_bignum *scalar1,
const struct crypto_bignum *element1,
const struct crypto_bignum *scalar2,
const struct crypto_bignum *element2,
u8 *confirm)
{
u8 element_b1[SAE_MAX_PRIME_LEN];
u8 element_b2[SAE_MAX_PRIME_LEN];
crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
sae->tmp->prime_len);
crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
sae->tmp->prime_len);
if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum op while generating SAE confirm - e1");
return ESP_FAIL;
}
if (crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
sae->tmp->prime_len) < 0) {
wpa_printf(MSG_ERROR, "SAE: failed bignum op while generating SAE confirm - e2");
return ESP_FAIL;
}
sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
scalar2, element_b2, sae->tmp->prime_len, confirm);
return ESP_OK;
}
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
{
const u8 *sc;
if (sae->tmp == NULL)
return;
return ESP_FAIL;
/* Send-Confirm */
sc = wpabuf_put(buf, 0);
@ -1350,18 +1374,26 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
if (sae->send_confirm < 0xffff)
sae->send_confirm++;
if (sae->tmp->ec)
sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ecc,
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ecc,
wpabuf_put(buf, SHA256_MAC_LEN));
else
sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ffc,
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ffc,
wpabuf_put(buf, SHA256_MAC_LEN));
if (sae->tmp->ec) {
if (sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ecc,
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ecc,
wpabuf_put(buf, SHA256_MAC_LEN))) {
wpa_printf(MSG_ERROR, "SAE: failed generate SAE confirm (ecc)");
return ESP_FAIL;
}
} else {
if (sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ffc,
sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ffc,
wpabuf_put(buf, SHA256_MAC_LEN))) {
wpa_printf(MSG_ERROR, "SAE: failed generate SAE confirm (ffc)");
return ESP_FAIL;
}
}
return ESP_OK;
}
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
@ -1370,28 +1402,35 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
if (len < 2 + SHA256_MAC_LEN) {
wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
return -1;
return ESP_FAIL;
}
wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
if (sae->tmp == NULL) {
wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available");
return -1;
return ESP_FAIL;
}
if (sae->tmp->ec)
sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ecc,
sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ecc,
verifier);
else
sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ffc,
sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ffc,
verifier);
if (sae->tmp->ec) {
if (sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ecc,
sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ecc,
verifier)) {
wpa_printf(MSG_ERROR, "SAE: failed to check SAE confirm (ecc)");
return ESP_FAIL;
}
} else {
if (sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
sae->tmp->peer_commit_element_ffc,
sae->tmp->own_commit_scalar,
sae->tmp->own_commit_element_ffc,
verifier)) {
wpa_printf(MSG_ERROR, "SAE: failed check SAE confirm (ffc)");
return ESP_FAIL;
}
}
if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
@ -1399,10 +1438,10 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
data + 2, SHA256_MAC_LEN);
wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
verifier, SHA256_MAC_LEN);
return -1;
return ESP_FAIL;
}
return 0;
return ESP_OK;
}
const char * sae_state_txt(enum sae_state state)

View file

@ -77,11 +77,11 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
const char *identifier, struct sae_data *sae);
int sae_process_commit(struct sae_data *sae);
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
const struct wpabuf *token, const char *identifier);
u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
const u8 **token, size_t *token_len, int *allowed_groups);
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
const char * sae_state_txt(enum sae_state state);

View file

@ -394,6 +394,9 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
memcpy(mic, hash, MD5_MAC_LEN);
break;
#ifdef CONFIG_IEEE80211W
#ifdef CONFIG_WPA3_SAE
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
#endif
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
return omac1_aes_128(key, buf, len, mic);
#endif
@ -514,13 +517,11 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
WPA_NONCE_LEN);
}
#ifdef CONFIG_IEEE80211W
if (use_sha256) {
sha256_prf(pmk, pmk_len, label, data, sizeof(data),
ptk, ptk_len);
}
else
#endif /* CONFIG_IEEE80211W */
{
sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len);
}

View file

@ -121,6 +121,7 @@
/* IEEE 802.11, 8.5.2 EAPOL-Key frames */
#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
#define WPA_KEY_INFO_TYPE_AKM_DEFINED 0
#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3

View file

@ -24,11 +24,16 @@
int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
int __must_check omac1_aes_vector(const u8 *key, size_t key_len,
size_t num_elem, const u8 *addr[],
const size_t *len, u8 *mac);
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len,
u8 *mac);
int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *data, size_t data_len);

View file

@ -14,7 +14,7 @@
#ifdef CONFIG_WPA3_SAE
#include "../common/sae.h"
#include "common/sae.h"
#include "esp_wifi_driver.h"
#include "rsn_supp/wpa.h"
@ -47,11 +47,17 @@ static struct wpabuf *wpa3_build_sae_commit(u8 *bssid)
return NULL;
}
// For reuse PWE after retry case
// memcpy(g_sae_data.tmp->bssid, bssid, ETH_ALEN);
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
sae_write_commit(&g_sae_data, buf, NULL, NULL); //no token
if (!buf) {
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
return NULL;
}
if (sae_write_commit(&g_sae_data, buf, NULL, NULL) != ESP_OK) {
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
wpabuf_free(buf);
return NULL;
}
g_sae_data.state = SAE_COMMITTED;
return buf;
@ -65,7 +71,16 @@ static struct wpabuf *wpa3_build_sae_confirm(void)
return NULL;
buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
sae_write_confirm(&g_sae_data, buf);
if (!buf) {
wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
return NULL;
}
if (sae_write_confirm(&g_sae_data, buf) != ESP_OK) {
wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
wpabuf_free(buf);
return NULL;
}
g_sae_data.state = SAE_CONFIRMED;
return buf;
@ -100,22 +115,22 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len)
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 -1;
return ESP_FAIL;
}
ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups);
if (ret) {
wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
return -1;
return ESP_FAIL;
}
ret = sae_process_commit(&g_sae_data);
if (ret) {
wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
return -1;
return ESP_FAIL;
}
return 0;
return ESP_OK;
}
static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
@ -123,21 +138,24 @@ static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
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 -1;
return ESP_FAIL;
}
sae_check_confirm(&g_sae_data, buf, len);
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);
memcpy(esp_wifi_sta_get_ap_info_prof_pmk_internal(), g_sae_data.pmk, PMK_LEN);
return 0;
return ESP_OK;
}
static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type)
{
int ret = 0;
int ret = ESP_OK;
switch (sae_msg_type) {
case SAE_MSG_COMMIT:
@ -149,7 +167,7 @@ static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type)
default:
wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%d)!",
sae_msg_type);
ret = -1;
ret = ESP_FAIL;
break;
}

View file

@ -245,6 +245,8 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
else if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
else if (sm->key_mgmt == WPA_KEY_MGMT_SAE)
ver = 0;
else
ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
@ -1661,7 +1663,8 @@ failed:
return -1;
}
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
sm->key_mgmt == WPA_KEY_MGMT_SAE) {
u8 *buf;
if (keydatalen % 8) {
#ifdef DEBUG_PRINT
@ -1832,6 +1835,9 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
#ifdef CONFIG_IEEE80211W
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
#ifdef CONFIG_WPA3_SAE
sm->key_mgmt != WPA_KEY_MGMT_SAE &&
#endif
#endif
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
#ifdef DEBUG_PRINT
@ -1843,14 +1849,16 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
#ifdef CONFIG_IEEE80211W
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
goto out;
}
} else
#endif
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
#ifdef DEBUG_PRINT
wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key "
"descriptor version (%d) is not 2.", ver);
@ -2073,8 +2081,6 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
sm->proto = wpa_proto;
if (auth_mode == WPA2_AUTH_ENT) {
sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X; /* for wpa2 enterprise */
} else if (auth_mode == WPA2_AUTH_PSK) {
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
} else if (auth_mode == WPA2_AUTH_PSK_SHA256) {
sm->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
} else if (auth_mode == WPA3_AUTH_PSK) {

View file

@ -85,7 +85,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
TEST_ASSERT( buf != NULL);
sae_write_commit(&sae, buf, NULL);// No anti-clogging token
sae_write_commit(&sae, buf, NULL, NULL);// No anti-clogging token
/* Parsing commit created by self will be detected as reflection attack*/
TEST_ASSERT(sae_parse_commit(&sae,
@ -125,14 +125,14 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
/* STA1 creates commit msg buffer*/
buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
TEST_ASSERT( buf1 != NULL);
sae_write_commit(&sae1, buf1, NULL);// No anti-clogging token
sae_write_commit(&sae1, buf1, NULL, NULL);// No anti-clogging token
ESP_LOG_BUFFER_HEXDUMP("SAE: Commit1", wpabuf_mhead_u8(buf1), wpabuf_len(buf1), ESP_LOG_INFO);
/* STA2 creates commit msg buffer*/
buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
TEST_ASSERT( buf2 != NULL);
sae_write_commit(&sae2, buf2, NULL);// No anti-clogging token
sae_write_commit(&sae2, buf2, NULL, NULL);// No anti-clogging token
ESP_LOG_BUFFER_HEXDUMP("SAE: Commit2", wpabuf_mhead_u8(buf2), wpabuf_len(buf2), ESP_LOG_INFO);
sae1.state = SAE_COMMITTED;
@ -205,20 +205,20 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
TEST_ASSERT(sae_set_group(&sae2, IANA_SECP256R1) == 0);
/* STA1 prepares for commit*/
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd), NULL, &sae1) == 0);
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd1), NULL, &sae1) == 0);
/* STA2 prepares for commit*/
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd), NULL, &sae2) == 0);
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), NULL, &sae2) == 0);
/* STA1 creates commit msg buffer*/
buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
TEST_ASSERT( buf1 != NULL);
sae_write_commit(&sae1, buf1, NULL);// No anti-clogging token
sae_write_commit(&sae1, buf1, NULL, NULL);// No anti-clogging token
/* STA2 creates commit msg buffer*/
buf2 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
TEST_ASSERT( buf2 != NULL);
sae_write_commit(&sae2, buf2, NULL);// No anti-clogging token
sae_write_commit(&sae2, buf2, NULL, NULL);// No anti-clogging token
sae1.state = SAE_COMMITTED;
sae2.state = SAE_COMMITTED;