mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/sae_sta_h2e_v4.3' into 'release/v4.3'
esp_wifi: WPA3 SAE H2E support for station (backport v4.3) See merge request espressif/esp-idf!18661
This commit is contained in:
commit
36decb6662
@ -222,6 +222,14 @@ typedef struct {
|
||||
bool required; /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */
|
||||
} wifi_pmf_config_t;
|
||||
|
||||
/** Configuration for SAE PWE derivation */
|
||||
typedef enum {
|
||||
WPA3_SAE_PWE_UNSPECIFIED,
|
||||
WPA3_SAE_PWE_HUNT_AND_PECK,
|
||||
WPA3_SAE_PWE_HASH_TO_ELEMENT,
|
||||
WPA3_SAE_PWE_BOTH,
|
||||
} wifi_sae_pwe_method_t;
|
||||
|
||||
/** @brief Soft-AP configuration settings for the ESP32 */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of ESP32 soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
|
||||
@ -251,6 +259,7 @@ 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 reserved:30; /**< Reserved for future feature set */
|
||||
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Whether SAE hash to element is enabled */
|
||||
} wifi_sta_config_t;
|
||||
|
||||
/** @brief Configuration data for ESP32 AP or STA.
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3bf3a0974dc628c36149098f869029b1b4bdf170
|
||||
Subproject commit 603c80b5814f449af4acfef3dc9aa02351b7a5ce
|
@ -32,6 +32,7 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/esp_supplicant/esp_hostap.c"
|
||||
"src/esp_supplicant/esp_wpa2.c"
|
||||
"src/esp_supplicant/esp_wpa_main.c"
|
||||
"src/esp_supplicant/esp_common.c"
|
||||
"src/esp_supplicant/esp_wpas_glue.c"
|
||||
"src/esp_supplicant/esp_wps.c"
|
||||
"src/esp_supplicant/esp_wpa3.c"
|
||||
@ -150,7 +151,6 @@ if(CONFIG_WPA_11KV_SUPPORT)
|
||||
"src/common/bss.c"
|
||||
"src/common/scan.c"
|
||||
"src/common/ieee802_11_common.c"
|
||||
"src/esp_supplicant/esp_common.c"
|
||||
"src/esp_supplicant/esp_scan.c"
|
||||
)
|
||||
else()
|
||||
|
@ -67,7 +67,6 @@ ifneq ($(CONFIG_WPA_11KV_SUPPORT), y)
|
||||
src/common/bss.o \
|
||||
src/common/scan.o \
|
||||
src/common/ieee802_11_common.o \
|
||||
src/esp_supplicant/esp_common.o \
|
||||
src/esp_supplicant/esp_scan.o
|
||||
endif
|
||||
|
||||
|
@ -29,9 +29,6 @@
|
||||
#define DEBUG_PRINT
|
||||
#endif
|
||||
|
||||
#if CONFIG_WPA_11KV_SUPPORT
|
||||
#define ROAMING_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_WPA_SCAN_CACHE
|
||||
#define SCAN_CACHE_SUPPORTED
|
||||
|
@ -25,6 +25,9 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#define WPA_CIPHER_GCMP BIT(6)
|
||||
#define WPA_CIPHER_SMS4 BIT(10)
|
||||
#define WPA_CIPHER_GCMP_256 BIT(11)
|
||||
#define WPA_CIPHER_BIP_GMAC_128 BIT(12)
|
||||
#define WPA_CIPHER_BIP_GMAC_256 BIT(13)
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
#define WPA_KEY_MGMT_PSK BIT(1)
|
||||
|
@ -157,6 +157,7 @@
|
||||
#define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99
|
||||
#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
|
||||
#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123
|
||||
#define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126
|
||||
|
||||
/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */
|
||||
#define WLAN_REASON_UNSPECIFIED 1
|
||||
@ -227,6 +228,7 @@
|
||||
#define WLAN_EID_FILS_INDICATION 240
|
||||
#define WLAN_EID_DILS 241
|
||||
#define WLAN_EID_FRAGMENT 242
|
||||
#define WLAN_EID_RSNX 244
|
||||
#define WLAN_EID_EXTENSION 255
|
||||
|
||||
/* Element ID Extension (EID 255) values */
|
||||
@ -248,6 +250,12 @@
|
||||
#define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33
|
||||
#define WLAN_EID_EXT_HE_CAPABILITIES 35
|
||||
#define WLAN_EID_EXT_HE_OPERATION 36
|
||||
#define WLAN_EID_EXT_REJECTED_GROUPS 92
|
||||
#define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93
|
||||
|
||||
/* Extended RSN Capabilities */
|
||||
/* bits 0-3: Field length (n-1) */
|
||||
#define WLAN_RSNX_CAPAB_SAE_H2E 5
|
||||
|
||||
#define WLAN_EXT_CAPAB_BSS_TRANSITION 19
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,8 +21,9 @@
|
||||
#define SAE_KEYSEED_KEY_LEN 32
|
||||
#define SAE_MAX_PRIME_LEN 512
|
||||
#define SAE_MAX_ECC_PRIME_LEN 66
|
||||
#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN)
|
||||
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN)
|
||||
#define SAE_MAX_HASH_LEN 64
|
||||
#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN + 255)
|
||||
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN)
|
||||
|
||||
/* Special value returned by sae_parse_commit() */
|
||||
#define SAE_SILENTLY_DISCARD 65535
|
||||
@ -45,6 +46,20 @@ struct sae_temporary_data {
|
||||
struct crypto_bignum *prime_buf;
|
||||
struct crypto_bignum *order_buf;
|
||||
char *pw_id;
|
||||
int order_len;
|
||||
struct wpabuf *own_rejected_groups;
|
||||
struct wpabuf *peer_rejected_groups;
|
||||
unsigned int own_addr_higher:1;
|
||||
};
|
||||
|
||||
struct sae_pt {
|
||||
struct sae_pt *next;
|
||||
int group;
|
||||
struct crypto_ec *ec;
|
||||
struct crypto_ec_point *ecc_pt;
|
||||
|
||||
const struct dh_group *dh;
|
||||
struct crypto_bignum *ffc_pt;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -66,6 +81,8 @@ struct sae_data {
|
||||
unsigned int sync; /* protocol instance variable: Sync */
|
||||
u16 rc; /* protocol instance variable: Rc (received send-confirm) */
|
||||
struct sae_temporary_data *tmp;
|
||||
struct crypto_bignum *peer_commit_scalar_accepted;
|
||||
unsigned int h2e:1;
|
||||
};
|
||||
|
||||
int sae_set_group(struct sae_data *sae, int group);
|
||||
@ -74,16 +91,32 @@ void sae_clear_data(struct sae_data *sae);
|
||||
|
||||
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
||||
const u8 *password, size_t password_len,
|
||||
const char *identifier, struct sae_data *sae);
|
||||
struct sae_data *sae);
|
||||
int sae_prepare_commit_pt(struct sae_data *sae, struct sae_pt *pt,
|
||||
const u8 *addr1, const u8 *addr2,
|
||||
int *rejected_groups);
|
||||
int sae_process_commit(struct sae_data *sae);
|
||||
int sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
||||
const struct wpabuf *token, const char *identifier);
|
||||
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);
|
||||
const u8 **token, size_t *token_len, int *allowed_groups,
|
||||
int h2e);
|
||||
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);
|
||||
size_t sae_ecc_prime_len_2_hash_len(size_t prime_len);
|
||||
size_t sae_ffc_prime_len_2_hash_len(size_t prime_len);
|
||||
struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len,
|
||||
const u8 *password, size_t password_len,
|
||||
const char *identifier);
|
||||
struct crypto_ec_point *
|
||||
sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
|
||||
const u8 *addr1, const u8 *addr2);
|
||||
struct crypto_bignum *
|
||||
sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
|
||||
const u8 *addr1, const u8 *addr2);
|
||||
void sae_deinit_pt(struct sae_pt *pt);
|
||||
|
||||
#endif /* SAE_H */
|
||||
#endif /* CONFIG_WPA3_SAE */
|
||||
|
@ -98,6 +98,33 @@ static int wpa_key_mgmt_to_bitfield(const u8 *s)
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NO_WPA2 */
|
||||
|
||||
int wpa_cipher_valid_mgmt_group(int cipher)
|
||||
{
|
||||
return cipher == WPA_CIPHER_AES_128_CMAC ||
|
||||
cipher == WPA_CIPHER_BIP_GMAC_128 ||
|
||||
cipher == WPA_CIPHER_BIP_GMAC_256;
|
||||
}
|
||||
|
||||
int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
|
||||
struct wpa_ie_data *data)
|
||||
{
|
||||
uint8_t rsnxe_capa = 0;
|
||||
uint8_t sae_pwe = esp_wifi_sta_get_config_sae_pwe_h2e_internal();
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
if (rsnxe_ie_len < 1) {
|
||||
return -1;
|
||||
}
|
||||
rsnxe_capa = rsnxe_ie[2];
|
||||
if (sae_pwe == 1 && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))){
|
||||
wpa_printf(MSG_ERROR, "SAE H2E required, but not supported by the AP");
|
||||
return -1;
|
||||
}
|
||||
data->rsnxe_capa = rsnxe_capa;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wpa_parse_wpa_ie_rsn - Parse RSN IE
|
||||
* @rsn_ie: Buffer containing RSN IE
|
||||
@ -436,7 +463,8 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
ie1d.group_cipher == ie2d.group_cipher &&
|
||||
ie1d.key_mgmt == ie2d.key_mgmt &&
|
||||
ie1d.capabilities == ie2d.capabilities &&
|
||||
ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
|
||||
ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher &&
|
||||
ie1d.rsnxe_capa == ie2d.rsnxe_capa)
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
@ -87,6 +87,8 @@
|
||||
#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20)
|
||||
|
||||
#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
|
||||
|
||||
#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val))
|
||||
@ -290,6 +292,7 @@ struct wpa_ie_data {
|
||||
size_t num_pmkid;
|
||||
const u8 *pmkid;
|
||||
int mgmt_group_cipher;
|
||||
uint8_t rsnxe_capa;
|
||||
};
|
||||
|
||||
struct rsn_sppamsdu_sup {
|
||||
@ -301,7 +304,10 @@ const char * wpa_cipher_txt(int cipher);
|
||||
|
||||
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
|
||||
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
||||
u8 *mic);
|
||||
int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
|
@ -653,6 +653,26 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *c,
|
||||
struct crypto_bignum *d);
|
||||
|
||||
/**
|
||||
* crypto_bignum_sqrmod - c = a^2 (mod b)
|
||||
* @a: Bignum
|
||||
* @b: Bignum
|
||||
* @c: Bignum; used to store the result of a^2 % b
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int crypto_bignum_sqrmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c);
|
||||
/**
|
||||
* crypto_bignum_rshift - r = a >> n
|
||||
* @a: Bignum
|
||||
* @n: Number of bits
|
||||
* @r: Bignum; used to store the result of a >> n
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
|
||||
struct crypto_bignum *r);
|
||||
|
||||
/**
|
||||
* crypto_bignum_cmp - Compare two bignums
|
||||
* @a: Bignum
|
||||
@ -729,6 +749,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e);
|
||||
*/
|
||||
size_t crypto_ec_prime_len_bits(struct crypto_ec *e);
|
||||
|
||||
/**
|
||||
* crypto_ec_order_len - Get length of the order in octets
|
||||
* @e: EC context from crypto_ec_init()
|
||||
* Returns: Length of the order defining the group
|
||||
*/
|
||||
size_t crypto_ec_order_len(struct crypto_ec *e);
|
||||
|
||||
/**
|
||||
* crypto_ec_get_prime - Get prime defining an EC group
|
||||
* @e: EC context from crypto_ec_init()
|
||||
@ -749,6 +776,14 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e);
|
||||
* Internal data structure for EC implementation to represent a point. The
|
||||
* contents is specific to the used crypto library.
|
||||
*/
|
||||
|
||||
/**
|
||||
* crypto_ec_get_b - Get 'b' coeffiecient of an EC group's curve
|
||||
* @e: EC context from crypto_ec_init()
|
||||
* Returns: 'b' coefficient (bignum) of the group
|
||||
*/
|
||||
const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e);
|
||||
|
||||
struct crypto_ec_point;
|
||||
|
||||
/**
|
||||
|
@ -46,6 +46,21 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
|
||||
{
|
||||
|
||||
mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
|
||||
if (bn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_mpi_init(bn);
|
||||
mbedtls_mpi_lset(bn, val);
|
||||
|
||||
return (struct crypto_bignum *)bn;
|
||||
}
|
||||
|
||||
|
||||
void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
|
||||
{
|
||||
mbedtls_mpi_free((mbedtls_mpi *)n);
|
||||
@ -163,6 +178,39 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_sqrmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
int res;
|
||||
struct crypto_bignum *tmp = crypto_bignum_init();
|
||||
if (!tmp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mbedtls_mpi_copy((mbedtls_mpi *) tmp,(const mbedtls_mpi *) a);
|
||||
res = crypto_bignum_mulmod(a,tmp,b,c);
|
||||
|
||||
crypto_bignum_deinit(tmp, 0);
|
||||
return res ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
|
||||
struct crypto_bignum *r)
|
||||
{
|
||||
int res;
|
||||
res = mbedtls_mpi_copy((mbedtls_mpi *) r,(const mbedtls_mpi *) a);
|
||||
if (res) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = mbedtls_mpi_shift_r((mbedtls_mpi *)r, n);
|
||||
return res ? -1 : 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int crypto_bignum_cmp(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b)
|
||||
{
|
||||
|
@ -107,6 +107,11 @@ size_t crypto_ec_prime_len(struct crypto_ec *e)
|
||||
return mbedtls_mpi_size(&e->group.P);
|
||||
}
|
||||
|
||||
size_t crypto_ec_order_len(struct crypto_ec *e)
|
||||
{
|
||||
return mbedtls_mpi_size(&e->group.N);
|
||||
}
|
||||
|
||||
|
||||
size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
|
||||
{
|
||||
@ -144,6 +149,12 @@ const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
|
||||
}
|
||||
|
||||
|
||||
const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e)
|
||||
{
|
||||
return (const struct crypto_bignum *) &e->group.B;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
|
||||
{
|
||||
mbedtls_ecp_point_free((mbedtls_ecp_point *) p);
|
||||
|
@ -3,7 +3,6 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
#include "esp_event.h"
|
||||
@ -23,6 +22,7 @@
|
||||
|
||||
struct wpa_supplicant g_wpa_supp;
|
||||
|
||||
#if defined(CONFIG_WPA_11KV_SUPPORT)
|
||||
static TaskHandle_t s_supplicant_task_hdl = NULL;
|
||||
static void *s_supplicant_evt_queue = NULL;
|
||||
static void *s_supplicant_api_lock = NULL;
|
||||
@ -431,6 +431,93 @@ void esp_set_rm_enabled_ie(void)
|
||||
}
|
||||
}
|
||||
|
||||
static size_t get_rm_enabled_ie(uint8_t *ie, size_t len)
|
||||
{
|
||||
uint8_t rrm_ie[7] = {0};
|
||||
uint8_t rrm_ie_len = 5;
|
||||
uint8_t *pos = rrm_ie;
|
||||
|
||||
if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
|
||||
*pos++ = rrm_ie_len;
|
||||
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
|
||||
|
||||
*pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
|
||||
#ifdef SCAN_CACHE_SUPPORTED
|
||||
WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
|
||||
#endif
|
||||
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
|
||||
|
||||
os_memcpy(ie, rrm_ie, sizeof(rrm_ie));
|
||||
|
||||
return rrm_ie_len + 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
|
||||
{
|
||||
uint8_t ext_caps_ie[5] = {0};
|
||||
uint8_t ext_caps_ie_len = 3;
|
||||
uint8_t *pos = ext_caps_ie;
|
||||
|
||||
if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPAB;
|
||||
*pos++ = ext_caps_ie_len;
|
||||
*pos++ = 0;
|
||||
*pos++ = 0;
|
||||
#define CAPAB_BSS_TRANSITION BIT(3)
|
||||
*pos |= CAPAB_BSS_TRANSITION;
|
||||
#undef CAPAB_BSS_TRANSITION
|
||||
os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie));
|
||||
|
||||
return ext_caps_ie_len + 2;
|
||||
}
|
||||
|
||||
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 + ies_len);
|
||||
if (!ie) {
|
||||
wpa_printf(MSG_ERROR, "failed to allocate ie");
|
||||
return;
|
||||
}
|
||||
pos = ie;
|
||||
ie_len = get_extended_caps_ie(pos, len);
|
||||
pos += ie_len;
|
||||
len -= ie_len;
|
||||
#ifdef CONFIG_WPA_11KV_SUPPORT
|
||||
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 /* CONFIG_MBO */
|
||||
#endif
|
||||
if (ies_len) {
|
||||
os_memcpy(pos, ies, ies_len);
|
||||
pos += ies_len;
|
||||
len -= ies_len;
|
||||
}
|
||||
esp_wifi_unset_appie_internal(WIFI_APPIE_ASSOC_REQ);
|
||||
esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_REQ, ie, ASSOC_IE_LEN - len, 0);
|
||||
os_free(ie);
|
||||
#undef ASSOC_IE_LEN
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPA_11KV_SUPPORT
|
||||
void esp_get_tx_power(uint8_t *tx_power)
|
||||
{
|
||||
#define DEFAULT_MAX_TX_POWER 19 /* max tx power is 19.5 dbm */
|
||||
@ -506,3 +593,4 @@ int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
struct wpa_funcs;
|
||||
|
||||
#ifdef ROAMING_SUPPORT
|
||||
#ifdef CONFIG_WPA_11KV_SUPPORT
|
||||
struct ieee_mgmt_frame {
|
||||
u8 sender[ETH_ALEN];
|
||||
u8 channel;
|
||||
@ -47,18 +47,7 @@ void esp_supplicant_common_deinit(void);
|
||||
#include "esp_wnm.h"
|
||||
|
||||
static inline void esp_set_rm_enabled_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;
|
||||
}
|
||||
|
||||
#endif
|
||||
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool add_mdie);
|
||||
#endif
|
||||
|
@ -113,6 +113,7 @@ typedef struct {
|
||||
size_t num_pmkid;
|
||||
const u8 *pmkid;
|
||||
int mgmt_group_cipher;
|
||||
uint8_t rsnxe_capa;
|
||||
} wifi_wpa_ie_t;
|
||||
|
||||
struct wpa_funcs {
|
||||
@ -137,6 +138,7 @@ 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);
|
||||
int (*wpa_sta_set_ap_rsnxe)(const u8 *rsnxe, size_t rsnxe_ie_len);
|
||||
};
|
||||
|
||||
struct wpa2_funcs {
|
||||
@ -274,5 +276,8 @@ esp_err_t esp_wifi_action_tx_req(uint8_t type, uint8_t channel,
|
||||
uint32_t wait_time_ms, const wifi_action_tx_req_t *req);
|
||||
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);
|
||||
uint8_t esp_wifi_sta_get_config_sae_pwe_h2e_internal(void);
|
||||
uint8_t esp_wifi_sta_get_use_h2e_internal(void);
|
||||
void esp_wifi_sta_disable_wpa2_authmode_internal(void);
|
||||
|
||||
#endif /* _ESP_WIFI_DRIVER_H_ */
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_WPA3_SAE
|
||||
|
||||
@ -19,6 +11,7 @@
|
||||
#include "esp_wifi_driver.h"
|
||||
#include "rsn_supp/wpa.h"
|
||||
|
||||
static struct sae_pt *g_sae_pt;
|
||||
static struct sae_data g_sae_data;
|
||||
static struct wpabuf *g_sae_token = NULL;
|
||||
static struct wpabuf *g_sae_commit = NULL;
|
||||
@ -30,7 +23,13 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid)
|
||||
int default_group = IANA_SECP256R1;
|
||||
u32 len = 0;
|
||||
u8 own_addr[ETH_ALEN];
|
||||
const u8 *pw;
|
||||
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_sta_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);
|
||||
}
|
||||
|
||||
if (wpa_sta_cur_pmksa_matches_akm()) {
|
||||
wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
|
||||
@ -59,8 +58,16 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
|
||||
if (sae_prepare_commit(own_addr, bssid, pw, strlen((const char *)pw), NULL, &g_sae_data) < 0) {
|
||||
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) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -128,6 +135,10 @@ void esp_wpa3_free_sae_data(void)
|
||||
g_sae_confirm = NULL;
|
||||
}
|
||||
sae_clear_data(&g_sae_data);
|
||||
if (g_sae_pt) {
|
||||
sae_deinit_pt(g_sae_pt);
|
||||
g_sae_pt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len)
|
||||
@ -167,11 +178,23 @@ static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
|
||||
if (status == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
|
||||
if (g_sae_token)
|
||||
wpabuf_free(g_sae_token);
|
||||
g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2);
|
||||
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);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups);
|
||||
ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups,
|
||||
status == WLAN_STATUS_SAE_HASH_TO_ELEMENT);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
|
||||
return ret;
|
||||
|
@ -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-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
@ -201,6 +193,7 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t
|
||||
data->capabilities = ie.capabilities;
|
||||
data->pmkid = ie.pmkid;
|
||||
data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher);
|
||||
data->rsnxe_capa = ie.rsnxe_capa;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -226,7 +219,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ROAMING_SUPPORT
|
||||
#ifndef CONFIG_WPA_11KV_SUPPORT
|
||||
static inline int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
|
||||
{
|
||||
wpa_cb->wpa_sta_rx_mgmt = NULL;
|
||||
@ -242,7 +235,7 @@ int esp_supplicant_init(void)
|
||||
int ret = ESP_OK;
|
||||
struct wpa_funcs *wpa_cb;
|
||||
|
||||
wpa_cb = (struct wpa_funcs *)os_malloc(sizeof(struct wpa_funcs));
|
||||
wpa_cb = (struct wpa_funcs *)os_zalloc(sizeof(struct wpa_funcs));
|
||||
if (!wpa_cb) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
@ -267,6 +260,7 @@ int esp_supplicant_init(void)
|
||||
wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
|
||||
wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
|
||||
wpa_cb->wpa_config_done = wpa_config_done;
|
||||
wpa_cb->wpa_sta_set_ap_rsnxe = wpa_sm_set_ap_rsnxe;
|
||||
|
||||
esp_wifi_register_wpa3_cb(wpa_cb);
|
||||
ret = esp_supplicant_common_init(wpa_cb);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "rsn_supp/wpa_ie.h"
|
||||
#include "esp_supplicant/esp_wpas_glue.h"
|
||||
#include "esp_supplicant/esp_wifi_driver.h"
|
||||
#include "esp_supplicant/esp_common_i.h"
|
||||
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/sha1.h"
|
||||
@ -580,6 +581,8 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
||||
struct wpa_eapol_ie_parse ie;
|
||||
struct wpa_ptk *ptk;
|
||||
int res;
|
||||
u8 *kde, *kde_buf = NULL;
|
||||
size_t kde_len;
|
||||
|
||||
wpa_sm_set_state(WPA_FIRST_HALF_4WAY_HANDSHAKE);
|
||||
|
||||
@ -637,16 +640,30 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
||||
sm->tptk_set = 1;
|
||||
sm->ptk_set = 0;
|
||||
sm->key_install = true;
|
||||
kde = sm->assoc_wpa_ie;
|
||||
kde_len = sm->assoc_wpa_ie_len;
|
||||
kde_buf = os_malloc(kde_len +
|
||||
sm->assoc_rsnxe_len);
|
||||
if (!kde_buf)
|
||||
goto failed;
|
||||
os_memcpy(kde_buf, kde, kde_len);
|
||||
kde = kde_buf;
|
||||
|
||||
if (sm->assoc_rsnxe && sm->assoc_rsnxe_len) {
|
||||
os_memcpy(kde + kde_len, sm->assoc_rsnxe, sm->assoc_rsnxe_len);
|
||||
kde_len += sm->assoc_rsnxe_len;
|
||||
}
|
||||
|
||||
if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
|
||||
sm->assoc_wpa_ie, sm->assoc_wpa_ie_len,
|
||||
ptk))
|
||||
kde, kde_len, ptk))
|
||||
goto failed;
|
||||
|
||||
os_free(kde_buf);
|
||||
memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
|
||||
return;
|
||||
|
||||
failed:
|
||||
os_free(kde_buf);
|
||||
wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
|
||||
}
|
||||
|
||||
@ -1106,6 +1123,22 @@ int ieee80211w_set_keys(struct wpa_sm *sm,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm->proto == WPA_PROTO_RSN &&
|
||||
((sm->ap_rsnxe && !ie->rsnxe) ||
|
||||
(!sm->ap_rsnxe && ie->rsnxe) ||
|
||||
(sm->ap_rsnxe && ie->rsnxe &&
|
||||
(sm->ap_rsnxe_len != ie->rsnxe_len ||
|
||||
os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0)))) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
|
||||
wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp",
|
||||
sm->ap_rsnxe, sm->ap_rsnxe_len);
|
||||
wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
|
||||
ie->rsnxe, ie->rsnxe_len);
|
||||
wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1273,6 +1306,9 @@ int ieee80211w_set_keys(struct wpa_sm *sm,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (ie.transition_disable)
|
||||
esp_wifi_sta_disable_wpa2_authmode_internal();
|
||||
|
||||
if (sm->key_install && sm->key_info & WPA_KEY_INFO_INSTALL) {
|
||||
wpa_supplicant_install_ptk(sm, KEY_FLAG_RX);
|
||||
}
|
||||
@ -2117,6 +2153,8 @@ bool wpa_sm_init(char * payload, WPA_SEND_FUNC snd_func,
|
||||
sm->wpa_deauthenticate = wpa_deauth;
|
||||
sm->wpa_neg_complete = wpa_neg_complete;
|
||||
sm->key_install = false;
|
||||
sm->ap_rsnxe = NULL;
|
||||
sm->assoc_rsnxe = NULL;
|
||||
|
||||
spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_STA);
|
||||
sm->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE);
|
||||
@ -2140,6 +2178,10 @@ void wpa_sm_deinit(void)
|
||||
{
|
||||
struct wpa_sm *sm = &gWpaSm;
|
||||
pmksa_cache_deinit(sm->pmksa);
|
||||
os_free(sm->ap_rsnxe);
|
||||
sm->ap_rsnxe = NULL;
|
||||
os_free(sm->assoc_rsnxe);
|
||||
sm->assoc_rsnxe = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -2182,6 +2224,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
|
||||
int res = 0;
|
||||
struct wpa_sm *sm = &gWpaSm;
|
||||
bool use_pmk_cache = true;
|
||||
u8 assoc_rsnxe[20];
|
||||
size_t assoc_rsnxe_len = sizeof(assoc_rsnxe);
|
||||
|
||||
/* Incase AP has changed it's SSID, don't try with PMK caching for SAE connection */
|
||||
/* Ideally we should use network_ctx for this purpose however currently network profile block
|
||||
@ -2237,6 +2281,14 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
|
||||
if (res < 0)
|
||||
return -1;
|
||||
sm->assoc_wpa_ie_len = res;
|
||||
res = wpa_gen_rsnxe(sm ,assoc_rsnxe, assoc_rsnxe_len);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
assoc_rsnxe_len = res;
|
||||
res = wpa_sm_set_assoc_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
esp_set_assoc_ie((uint8_t *)bssid, assoc_rsnxe, assoc_rsnxe_len, true);
|
||||
os_memset(sm->ssid, 0, sizeof(sm->ssid));
|
||||
os_memcpy(sm->ssid, ssid, ssid_len);
|
||||
sm->ssid_len = ssid_len;
|
||||
@ -2481,4 +2533,55 @@ void wpa_sta_clear_curr_pmksa(void) {
|
||||
pmksa_cache_clear_current(sm);
|
||||
}
|
||||
|
||||
struct wpa_sm * get_wpa_sm(void)
|
||||
{
|
||||
return &gWpaSm;
|
||||
}
|
||||
|
||||
int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len)
|
||||
{
|
||||
struct wpa_sm *sm = &gWpaSm;
|
||||
if (!sm)
|
||||
return -1;
|
||||
|
||||
os_free(sm->ap_rsnxe);
|
||||
if (!ie || len == 0) {
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
|
||||
sm->ap_rsnxe = NULL;
|
||||
sm->ap_rsnxe_len = 0;
|
||||
} else {
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
|
||||
sm->ap_rsnxe = os_memdup(ie, len);
|
||||
if (!sm->ap_rsnxe)
|
||||
return -1;
|
||||
|
||||
sm->ap_rsnxe_len = len;
|
||||
}
|
||||
|
||||
sm->sae_pwe = esp_wifi_sta_get_config_sae_pwe_h2e_internal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
|
||||
{
|
||||
if (!sm)
|
||||
return -1;
|
||||
|
||||
os_free(sm->assoc_rsnxe);
|
||||
if (!ie || len == 0) {
|
||||
sm->assoc_rsnxe = NULL;
|
||||
sm->assoc_rsnxe_len = 0;
|
||||
} else {
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: set own RSNXE", ie, len);
|
||||
sm->assoc_rsnxe = os_memdup(ie, len);
|
||||
if (!sm->assoc_rsnxe)
|
||||
return -1;
|
||||
|
||||
sm->assoc_rsnxe_len = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // ESP_SUPPLICANT
|
||||
|
@ -136,4 +136,12 @@ unsigned cipher_type_map_public_to_supp(wifi_cipher_type_t cipher);
|
||||
|
||||
void wpa_sta_clear_curr_pmksa(void);
|
||||
|
||||
int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len);
|
||||
|
||||
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
|
||||
|
||||
struct wpa_sm * get_wpa_sm(void);
|
||||
|
||||
void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
|
||||
|
||||
#endif /* WPA_H */
|
||||
|
@ -52,12 +52,15 @@ struct wpa_sm {
|
||||
void *network_ctx;
|
||||
|
||||
int rsn_enabled; /* Whether RSN is enabled in configuration */
|
||||
int sae_pwe; /* SAE PWE generation options */
|
||||
|
||||
int countermeasures; /*TKIP countermeasures state flag, 1:in countermeasures state*/
|
||||
ETSTimer cm_timer;
|
||||
|
||||
u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
|
||||
size_t assoc_wpa_ie_len;
|
||||
u8 *assoc_rsnxe; /* Own RSNXE from (Re)AssocReq */
|
||||
size_t assoc_rsnxe_len;
|
||||
|
||||
u8 eapol_version;
|
||||
|
||||
@ -69,8 +72,8 @@ struct wpa_sm {
|
||||
unsigned int proto;
|
||||
enum wpa_states wpa_state;
|
||||
|
||||
u8 *ap_wpa_ie, *ap_rsn_ie;
|
||||
size_t ap_wpa_ie_len, ap_rsn_ie_len;
|
||||
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
|
||||
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
|
||||
|
||||
bool key_install;
|
||||
|
||||
|
@ -35,6 +35,8 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
{
|
||||
if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) {
|
||||
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
|
||||
} else if (wpa_ie_len >=1 && wpa_ie[0] == WLAN_EID_RSNX){
|
||||
return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
|
||||
} else if (wpa_ie[0] == WLAN_EID_WAPI) {
|
||||
return 0;
|
||||
}
|
||||
@ -300,6 +302,34 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
|
||||
}
|
||||
|
||||
|
||||
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
|
||||
{
|
||||
u8 *pos = rsnxe;
|
||||
u16 capab = 0;
|
||||
size_t flen;
|
||||
|
||||
if (wpa_key_mgmt_sae(sm->key_mgmt) &&
|
||||
(sm->sae_pwe == 1 || sm->sae_pwe == 2)) {
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||
}
|
||||
|
||||
flen = (capab & 0xff00) ? 2 : 1;
|
||||
if (!capab)
|
||||
return 0; /* no supported extended RSN capabilities */
|
||||
if (rsnxe_len < 2 + flen)
|
||||
return -1;
|
||||
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
|
||||
|
||||
*pos++ = WLAN_EID_RSNX;
|
||||
*pos++ = flen;
|
||||
*pos++ = capab & 0x00ff;
|
||||
capab >>= 8;
|
||||
if (capab)
|
||||
*pos++ = capab;
|
||||
|
||||
return pos - rsnxe;
|
||||
}
|
||||
|
||||
/**
|
||||
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
|
||||
* @pos: Pointer to the IE header
|
||||
@ -360,6 +390,15 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) {
|
||||
ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"WPA: Transition Disable KDE in EAPOL-Key",
|
||||
pos, pos[1] + 2);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -400,6 +439,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||
ie->rsn_ie_len = pos[1] + 2;
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
|
||||
ie->rsn_ie, ie->rsn_ie_len);
|
||||
} else if (*pos == WLAN_EID_RSNX) {
|
||||
ie->rsnxe = pos;
|
||||
ie->rsnxe_len = pos[1] + 2;
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
|
||||
ie->rsnxe, ie->rsnxe_len);
|
||||
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
||||
ret = wpa_parse_generic(pos, end, ie);
|
||||
if (ret < 0)
|
||||
|
@ -37,12 +37,16 @@ struct wpa_eapol_ie_parse {
|
||||
const u8 *reassoc_deadline;
|
||||
const u8 *key_lifetime;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
const u8 *transition_disable;
|
||||
size_t transition_disable_len;
|
||||
const u8 *rsnxe;
|
||||
size_t rsnxe_len;
|
||||
};
|
||||
|
||||
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||
struct wpa_eapol_ie_parse *ie);
|
||||
int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len);
|
||||
|
||||
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len);
|
||||
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
|
||||
struct wpa_ie_data *data);
|
||||
|
||||
|
191
components/wpa_supplicant/src/utils/const_time.h
Normal file
191
components/wpa_supplicant/src/utils/const_time.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Helper functions for constant time operations
|
||||
* Copyright (c) 2019, The Linux Foundation
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*
|
||||
* These helper functions can be used to implement logic that needs to minimize
|
||||
* externally visible differences in execution path by avoiding use of branches,
|
||||
* avoiding early termination or other time differences, and forcing same memory
|
||||
* access pattern regardless of values.
|
||||
*/
|
||||
|
||||
#ifndef CONST_TIME_H
|
||||
#define CONST_TIME_H
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
#define NO_UBSAN_UINT_OVERFLOW \
|
||||
__attribute__((no_sanitize("unsigned-integer-overflow")))
|
||||
#else
|
||||
#define NO_UBSAN_UINT_OVERFLOW
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* const_time_fill_msb - Fill all bits with MSB value
|
||||
* @val: Input value
|
||||
* Returns: Value with all the bits set to the MSB of the input val
|
||||
*/
|
||||
static inline unsigned int const_time_fill_msb(unsigned int val)
|
||||
{
|
||||
/* Move the MSB to LSB and multiple by -1 to fill in all bits. */
|
||||
return (val >> (sizeof(val) * 8 - 1)) * ~0U;
|
||||
}
|
||||
|
||||
|
||||
/* Returns: -1 if val is zero; 0 if val is not zero */
|
||||
static inline unsigned int const_time_is_zero(unsigned int val)
|
||||
NO_UBSAN_UINT_OVERFLOW
|
||||
{
|
||||
/* Set MSB to 1 for 0 and fill rest of bits with the MSB value */
|
||||
return const_time_fill_msb(~val & (val - 1));
|
||||
}
|
||||
|
||||
|
||||
/* Returns: -1 if a == b; 0 if a != b */
|
||||
static inline unsigned int const_time_eq(unsigned int a, unsigned int b)
|
||||
{
|
||||
return const_time_is_zero(a ^ b);
|
||||
}
|
||||
|
||||
|
||||
/* Returns: -1 if a == b; 0 if a != b */
|
||||
static inline u8 const_time_eq_u8(unsigned int a, unsigned int b)
|
||||
{
|
||||
return (u8) const_time_eq(a, b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_eq_bin - Constant time memory comparison
|
||||
* @a: First buffer to compare
|
||||
* @b: Second buffer to compare
|
||||
* @len: Number of octets to compare
|
||||
* Returns: -1 if buffers are equal, 0 if not
|
||||
*
|
||||
* This function is meant for comparing passwords or hash values where
|
||||
* difference in execution time or memory access pattern could provide external
|
||||
* observer information about the location of the difference in the memory
|
||||
* buffers. The return value does not behave like memcmp(), i.e.,
|
||||
* const_time_eq_bin() cannot be used to sort items into a defined order. Unlike
|
||||
* memcmp(), the execution time of const_time_eq_bin() does not depend on the
|
||||
* contents of the compared memory buffers, but only on the total compared
|
||||
* length.
|
||||
*/
|
||||
static inline unsigned int const_time_eq_bin(const void *a, const void *b,
|
||||
size_t len)
|
||||
{
|
||||
const u8 *aa = a;
|
||||
const u8 *bb = b;
|
||||
size_t i;
|
||||
u8 res = 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
res |= aa[i] ^ bb[i];
|
||||
|
||||
return const_time_is_zero(res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_select - Constant time unsigned int selection
|
||||
* @mask: 0 (false) or -1 (true) to identify which value to select
|
||||
* @true_val: Value to select for the true case
|
||||
* @false_val: Value to select for the false case
|
||||
* Returns: true_val if mask == -1, false_val if mask == 0
|
||||
*/
|
||||
static inline unsigned int const_time_select(unsigned int mask,
|
||||
unsigned int true_val,
|
||||
unsigned int false_val)
|
||||
{
|
||||
return (mask & true_val) | (~mask & false_val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_select_int - Constant time int selection
|
||||
* @mask: 0 (false) or -1 (true) to identify which value to select
|
||||
* @true_val: Value to select for the true case
|
||||
* @false_val: Value to select for the false case
|
||||
* Returns: true_val if mask == -1, false_val if mask == 0
|
||||
*/
|
||||
static inline int const_time_select_int(unsigned int mask, int true_val,
|
||||
int false_val)
|
||||
{
|
||||
return (int) const_time_select(mask, (unsigned int) true_val,
|
||||
(unsigned int) false_val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_select_u8 - Constant time u8 selection
|
||||
* @mask: 0 (false) or -1 (true) to identify which value to select
|
||||
* @true_val: Value to select for the true case
|
||||
* @false_val: Value to select for the false case
|
||||
* Returns: true_val if mask == -1, false_val if mask == 0
|
||||
*/
|
||||
static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val)
|
||||
{
|
||||
return (u8) const_time_select(mask, true_val, false_val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_select_s8 - Constant time s8 selection
|
||||
* @mask: 0 (false) or -1 (true) to identify which value to select
|
||||
* @true_val: Value to select for the true case
|
||||
* @false_val: Value to select for the false case
|
||||
* Returns: true_val if mask == -1, false_val if mask == 0
|
||||
*/
|
||||
static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val)
|
||||
{
|
||||
return (s8) const_time_select(mask, (unsigned int) true_val,
|
||||
(unsigned int) false_val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* const_time_select_bin - Constant time binary buffer selection copy
|
||||
* @mask: 0 (false) or -1 (true) to identify which value to copy
|
||||
* @true_val: Buffer to copy for the true case
|
||||
* @false_val: Buffer to copy for the false case
|
||||
* @len: Number of octets to copy
|
||||
* @dst: Destination buffer for the copy
|
||||
*
|
||||
* This function copies the specified buffer into the destination buffer using
|
||||
* operations with identical memory access pattern regardless of which buffer
|
||||
* is being copied.
|
||||
*/
|
||||
static inline void const_time_select_bin(u8 mask, const u8 *true_val,
|
||||
const u8 *false_val, size_t len,
|
||||
u8 *dst)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]);
|
||||
}
|
||||
|
||||
|
||||
static inline int const_time_memcmp(const void *a, const void *b, size_t len)
|
||||
{
|
||||
const u8 *aa = a;
|
||||
const u8 *bb = b;
|
||||
int diff, res = 0;
|
||||
unsigned int mask;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
do {
|
||||
len--;
|
||||
diff = (int) aa[len] - (int) bb[len];
|
||||
mask = const_time_is_zero((unsigned int) diff);
|
||||
res = const_time_select_int(mask, res, diff);
|
||||
} while (len);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* CONST_TIME_H */
|
@ -74,7 +74,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
||||
|
||||
TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0);
|
||||
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), NULL, &sae) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae) == 0);
|
||||
|
||||
buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
|
||||
|
||||
@ -84,7 +84,7 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
||||
|
||||
/* Parsing commit created by self will be detected as reflection attack*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae,
|
||||
wpabuf_mhead(buf), buf->used, NULL, 0, default_groups) == SAE_SILENTLY_DISCARD);
|
||||
wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD);
|
||||
|
||||
wpabuf_free2(buf);
|
||||
sae_clear_temp_data(&sae);
|
||||
@ -112,10 +112,10 @@ 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, pwd, strlen((const char *)pwd), NULL, &sae1) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae1) == 0);
|
||||
|
||||
/* STA2 prepares for commit*/
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd, strlen((const char *)pwd), NULL, &sae2) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd, strlen((const char *)pwd), &sae2) == 0);
|
||||
|
||||
/* STA1 creates commit msg buffer*/
|
||||
buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
|
||||
@ -135,11 +135,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
||||
|
||||
/* STA1 parses STA2 commit*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae1,
|
||||
wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0);
|
||||
wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0);
|
||||
|
||||
/* STA2 parses STA1 commit*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae2,
|
||||
wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0);
|
||||
wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0);
|
||||
|
||||
/* STA1 processes commit*/
|
||||
TEST_ASSERT(sae_process_commit(&sae1) == 0);
|
||||
@ -200,10 +200,10 @@ 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 *)pwd1), NULL, &sae1) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd1, strlen((const char *)pwd1), &sae1) == 0);
|
||||
|
||||
/* STA2 prepares for commit*/
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), NULL, &sae2) == 0);
|
||||
TEST_ASSERT(sae_prepare_commit(addr2, addr1, pwd2, strlen((const char *)pwd2), &sae2) == 0);
|
||||
|
||||
/* STA1 creates commit msg buffer*/
|
||||
buf1 = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
|
||||
@ -220,11 +220,11 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
|
||||
|
||||
/* STA1 parses STA2 commit*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae1,
|
||||
wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups) == 0);
|
||||
wpabuf_mhead(buf2), buf2->used, NULL, 0, default_groups, 0) == 0);
|
||||
|
||||
/* STA2 parses STA1 commit*/
|
||||
TEST_ASSERT(sae_parse_commit(&sae2,
|
||||
wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups) == 0);
|
||||
wpabuf_mhead(buf1), buf1->used, NULL, 0, default_groups, 0) == 0);
|
||||
|
||||
/* STA1 processes commit*/
|
||||
TEST_ASSERT(sae_process_commit(&sae1) == 0);
|
||||
|
@ -114,7 +114,8 @@ void wifi_init_sta(void)
|
||||
/* Setting a password implies station will connect to all security modes including WEP/WPA.
|
||||
* However these modes are deprecated and not advisable to be used. Incase your Access point
|
||||
* doesn't support WPA2, these mode can be enabled by commenting below line */
|
||||
.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
|
||||
.threshold.authmode = WIFI_AUTH_WPA3_PSK,
|
||||
.sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
|
Loading…
Reference in New Issue
Block a user