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.
pull/5815/head
Nachiket Kukade 2020-04-29 18:47:23 +05:30
rodzic 6b76228fcb
commit d36663b798
13 zmienionych plików z 210 dodań i 118 usunięć

Wyświetl plik

@ -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"

Wyświetl plik

@ -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\
};

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Wyświetl plik

@ -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));
}

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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;