From 6d55761f60837272ef9e6f3a39847f8d1ddf7836 Mon Sep 17 00:00:00 2001 From: Shyamal Khachane Date: Tue, 14 Jun 2022 11:31:52 +0530 Subject: [PATCH] OWE support for station --- components/esp_rom/esp32c2/ld/esp32c2.rom.ld | 4 - components/esp_wifi/Kconfig | 9 + components/esp_wifi/include/esp_wifi_types.h | 6 +- components/esp_wifi/lib | 2 +- components/wpa_supplicant/CMakeLists.txt | 7 +- .../src/crypto/crypto_mbedtls-ec.c | 197 +++++++++++++++++ .../esp_supplicant/src/esp_owe.c | 34 +++ .../esp_supplicant/src/esp_owe_i.h | 23 ++ .../esp_supplicant/src/esp_wifi_driver.h | 5 +- .../esp_supplicant/src/esp_wpa_main.c | 9 +- components/wpa_supplicant/src/common/defs.h | 12 +- .../wpa_supplicant/src/common/wpa_common.c | 27 ++- .../wpa_supplicant/src/common/wpa_common.h | 2 + components/wpa_supplicant/src/crypto/crypto.h | 12 + components/wpa_supplicant/src/rsn_supp/wpa.c | 209 +++++++++++++++++- components/wpa_supplicant/src/rsn_supp/wpa.h | 8 + .../wpa_supplicant/src/rsn_supp/wpa_i.h | 4 + .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 6 +- components/wpa_supplicant/src/utils/common.h | 3 +- examples/wifi/scan/main/scan.c | 3 + 20 files changed, 562 insertions(+), 20 deletions(-) create mode 100644 components/wpa_supplicant/esp_supplicant/src/esp_owe.c create mode 100644 components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld index c3f3e2e7d3..a1b3805d9c 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld @@ -2082,7 +2082,6 @@ wep_decap = 0x40002028; dbg_hmac_rxtx_statis_dump = 0x4000202c; dbg_hmac_statis_dump = 0x40002030; ieee80211_send_action_vendor_spec = 0x40002034; -ieee80211_send_mgmt = 0x40002038; ieee80211_deauth_construct = 0x40002040; ieee80211_disassoc_construct = 0x40002044; ieee80211_vnd_lora_ie_size = 0x40002048; @@ -2091,7 +2090,6 @@ ieee80211_add_ssid = 0x40002050; ieee80211_add_rates = 0x40002054; ieee80211_add_xrates = 0x40002058; ieee80211_is_ht_cipher = 0x4000205c; -ieee80211_assoc_req_construct = 0x40002060; ieee80211_assoc_resp_construct = 0x40002064; ieee80211_setup_lr_rates = 0x40002068; ieee80211_ht_node_init = 0x4000206c; @@ -2144,10 +2142,8 @@ ieee80211_tx_mgt_cb = 0x4000212c; ieee80211_getcapinfo = 0x40002130; sta_rx_csa = 0x40002134; sta_recv_sa_query_resp = 0x40002144; -ieee80211_parse_beacon = 0x40002148; ieee80211_set_max_rate = 0x4000214c; ic_set_sta = 0x40002150; -ieee80211_match_security = 0x40002154; ieee80211_parse_wpa = 0x40002158; ieee80211_add_assoc_req_ies = 0x40002160; ieee80211_add_probe_req_ies = 0x40002164; diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index e3d9a90dc8..ad5cda4bf6 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -250,6 +250,15 @@ menu "Wi-Fi" 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. + config ESP32_WIFI_ENABLE_WPA3_OWE_STA + bool "Enable OWE STA" + default y + select WPA_MBEDTLS_CRYPTO + help + Select this option to allow the device to establish OWE 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. + config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" select PM_SLP_DEFAULT_PARAMS_OPT diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index 8c3c0f5aca..5068a5511f 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/components/esp_wifi/include/esp_wifi_types.h @@ -47,6 +47,8 @@ typedef struct { wifi_country_policy_t policy; /**< country policy */ } wifi_country_t; +/* Strength of authmodes */ +/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA2_ENTERPRISE < WPA3_PSK = WPA2_WPA3_PSK */ typedef enum { WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */ WIFI_AUTH_WEP, /**< authenticate mode : WEP */ @@ -57,6 +59,7 @@ typedef enum { WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */ WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */ WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */ + WIFI_AUTH_OWE, /**< authenticate mode : OWE */ WIFI_AUTH_MAX } wifi_auth_mode_t; @@ -250,7 +253,8 @@ typedef struct { uint32_t btm_enabled:1; /**< Whether BSS Transition Management is enabled for the connection */ uint32_t mbo_enabled:1; /**< Whether MBO is enabled for the connection */ uint32_t ft_enabled:1; /**< Whether FT is enabled for the connection */ - uint32_t reserved:28; /**< Reserved for future feature set */ + uint32_t owe_enabled:1; /**< Whether OWE is enabled for the connection */ + uint32_t reserved:27; /**< Reserved for future feature set */ } wifi_sta_config_t; /** @brief Configuration data for ESP32 AP or STA. diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index dd7254fb02..bf6e8acaa3 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit dd7254fb02c05aaa4d0c5f6f805a6e28998f9ab5 +Subproject commit bf6e8acaa3625cd6bb84a8f1531f0c39f8f4a6f8 diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 8987aba14d..738d5c8274 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -62,7 +62,8 @@ set(esp_srcs "esp_supplicant/src/esp_wpa2.c" "esp_supplicant/src/esp_wpas_glue.c" "esp_supplicant/src/esp_common.c" "esp_supplicant/src/esp_wps.c" - "esp_supplicant/src/esp_wpa3.c") + "esp_supplicant/src/esp_wpa3.c" + "esp_supplicant/src/esp_owe.c") if(CONFIG_ESP_WIFI_SOFTAP_SUPPORT) set(esp_srcs ${esp_srcs} "esp_supplicant/src/esp_hostap.c") endif() @@ -141,6 +142,7 @@ else() "src/crypto/sha1-pbkdf2.c" "src/crypto/sha1.c" "src/crypto/sha256-internal.c" + "src/crypto/sha256.c" "src/crypto/sha384-internal.c" "src/crypto/sha512-internal.c" "src/crypto/sha256.c") @@ -259,4 +261,7 @@ endif() if(CONFIG_WPA_WPS_SOFTAP_REGISTRAR) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_REGISTRAR) endif() +if(CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_STA) +endif() set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index eef2ce1be7..f9be1d19a6 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -3,6 +3,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + #ifdef ESP_PLATFORM #include "esp_system.h" #include "mbedtls/bignum.h" @@ -27,6 +30,12 @@ #define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES +#ifdef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT +#define ACCESS_ECDH(S, var) S->var +#else +#define ACCESS_ECDH(S, var) S->ctx.mbed_ecdh.var +#endif + #ifdef CONFIG_ECC struct crypto_ec { mbedtls_ecp_group group; @@ -994,4 +1003,192 @@ int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf) return len; } + +int crypto_mbedtls_get_grp_id(int group) +{ + switch(group) { + case IANA_SECP256R1: + return MBEDTLS_ECP_DP_SECP256R1; + case IANA_SECP384R1: + return MBEDTLS_ECP_DP_SECP384R1; + case IANA_SECP521R1: + return MBEDTLS_ECP_DP_SECP521R1; + default: + return MBEDTLS_ECP_DP_NONE; + } +} + +void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) +{ + mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; + if (!ctx) { + return; + } + mbedtls_ecdh_free(ctx); + os_free(ctx); + ctx = NULL; +} + +struct crypto_ecdh * crypto_ecdh_init(int group) +{ + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + mbedtls_ecdh_context *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + + if (!ctx) { + wpa_printf(MSG_ERROR, "Memory allocation failed for ecdh context"); + goto fail; + } + mbedtls_ecdh_init(ctx); + + if ((mbedtls_ecp_group_load(ACCESS_ECDH(&ctx, grp), crypto_mbedtls_get_grp_id(group))) != 0) { + wpa_printf(MSG_ERROR, "Failed to set up ECDH context with group info"); + goto fail; + } + + /* Initialize CTR_DRBG context */ + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed and setup CTR_DRBG entropy source for future reseeds */ + if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) { + wpa_printf(MSG_ERROR, "Seeding entropy source failed"); + goto fail; + } + + /* Generates ECDH keypair on elliptic curve */ + if (mbedtls_ecdh_gen_public(ACCESS_ECDH(&ctx, grp), ACCESS_ECDH(&ctx, d), ACCESS_ECDH(&ctx, Q), mbedtls_ctr_drbg_random, &ctr_drbg)!=0) { + wpa_printf(MSG_ERROR, "ECDH keypair on curve failed"); + goto fail; + } + return (struct crypto_ecdh *)ctx; +fail: + return NULL; +} + +struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int y) +{ + struct wpabuf *public_key = NULL; + uint8_t *buf = NULL; + mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; + size_t prime_len = ACCESS_ECDH(ctx, grp).pbits/8; + + buf = os_zalloc(y ? prime_len : 2 * prime_len); + if (!buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed"); + return NULL; + } + + /* Export an MPI into unsigned big endian binary data of fixed size */ + mbedtls_mpi_write_binary(ACCESS_ECDH(&ctx, Q).X, buf, prime_len); + public_key = wpabuf_alloc_copy(buf, 32); + os_free(buf); + return public_key; +} + +struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, + const u8 *key, size_t len) +{ + uint8_t *secret = 0; + size_t olen = 0, len_prime = 0; + struct crypto_bignum *bn_x = NULL; + struct crypto_ec_point *ec_pt = NULL; + uint8_t *px = NULL, *py = NULL, *buf = NULL; + struct crypto_key *pkey = NULL; + struct wpabuf *sh_secret = NULL; + int secret_key = 0; + + mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; + + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_entropy_context entropy; + + /* Initialize CTR_DRBG context */ + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed and setup CTR_DRBG entropy source for future reseeds */ + if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) { + wpa_printf(MSG_ERROR, "Seeding entropy source failed"); + goto cleanup; + } + len_prime = ACCESS_ECDH(ctx, grp).pbits/8; + bn_x = crypto_bignum_init_set(key, len); + + /* Initialize data for EC point */ + ec_pt = crypto_ec_point_init((struct crypto_ec*)ACCESS_ECDH(&ctx, grp)); + if (!ec_pt) { + wpa_printf(MSG_ERROR,"Initializing for EC point failed"); + goto cleanup; + } + + if (crypto_ec_point_solve_y_coord((struct crypto_ec*)ACCESS_ECDH(&ctx, grp), ec_pt, bn_x, inc_y) != 0) { + wpa_printf(MSG_ERROR,"Failed to solve for y coordinate"); + goto cleanup; + } + px = os_zalloc(len); + py = os_zalloc(len); + buf = os_zalloc(2*len); + + if (!px || !py || !buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed"); + goto cleanup; + } + if (crypto_ec_point_to_bin((struct crypto_ec*)ACCESS_ECDH(&ctx, grp), ec_pt, px, py) != 0) { + wpa_printf(MSG_ERROR,"Failed to write EC point value as binary data"); + goto cleanup; + } + + os_memcpy(buf, px, len); + os_memcpy(buf+len, py, len); + + pkey = crypto_ec_set_pubkey_point((struct crypto_ec_group*)ACCESS_ECDH(&ctx, grp), buf, len); + if (!pkey) { + wpa_printf(MSG_ERROR, "Failed to set point for peer's public key"); + goto cleanup; + } + + + mbedtls_pk_context *peer = (mbedtls_pk_context*)pkey; + + /* Setup ECDH context from EC key */ +/* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */ + if (ctx != NULL && peer != NULL) { + mbedtls_ecp_copy( ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->Q ); +#ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; +#endif + } else { + wpa_printf(MSG_ERROR, "Failed to set peer's ECDH context"); + goto cleanup; + } + int len_secret = inc_y ? 2*len : len; + secret = os_zalloc(len_secret); + if (!secret) { + wpa_printf(MSG_ERROR, "Allocation failed for secret"); + goto cleanup; + } + + /* Calculate secret + z = F(DH(x,Y)) */ + secret_key = mbedtls_ecdh_calc_secret(ctx, &olen, secret, len_prime, mbedtls_ctr_drbg_random, &ctr_drbg); + if (secret_key != 0) { + wpa_printf(MSG_ERROR, "Calculation of secret failed"); + goto cleanup; + } + sh_secret = wpabuf_alloc_copy(secret, len_secret); + +cleanup: + os_free(px); + os_free(py); + os_free(buf); + os_free(secret); + crypto_ec_free_key(pkey); + crypto_bignum_deinit(bn_x, 1); + crypto_ec_point_deinit(ec_pt, 1); + return sh_secret; +} + #endif /* CONFIG_ECC */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe.c b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c new file mode 100644 index 0000000000..8bf729c7af --- /dev/null +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifdef CONFIG_OWE_STA + +#include "crypto/crypto.h" +#include "esp_owe_i.h" +#include "rsn_supp/wpa.h" + +uint8_t *owe_build_dhie(uint16_t group) +{ + struct wpa_sm *sm = NULL; + sm = get_wpa_sm(); + return (uint8_t *)(owe_build_assoc_req(sm, group)); +} + +void owe_deinit(void) +{ + struct wpa_sm *sm; + sm = get_wpa_sm(); + if (sm->key_mgmt == WPA_KEY_MGMT_OWE) { + crypto_ecdh_deinit(sm->owe_ecdh); + sm->owe_ecdh = NULL; + } +} + +void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb) +{ + wpa_cb->owe_build_dhie = owe_build_dhie; + wpa_cb->owe_process_assoc_resp = owe_process_assoc_resp; +} +#endif /* CONFIG_OWE_STA */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h new file mode 100644 index 0000000000..44223f3854 --- /dev/null +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ESP_OWE_H +#define ESP_OWE_H + +#ifdef CONFIG_OWE_STA + +#include "esp_wifi_driver.h" + +#define OWE_PMK_LEN 32 +#define OWE_PMKID_LEN 16 +#define OWE_DH_GRP19 19 +#define OWE_PRIME_LEN 32 + +void owe_deinit(void); +void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb); + +#endif /* CONFIG_OWE_STA */ +#endif /* ESP_OWE_H */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index 7ea25d9a6d..778af824c1 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -71,6 +71,7 @@ enum { WAPI_AUTH_CERT = 0x0c, WPA2_AUTH_ENT_SHA384_SUITE_B = 0x0d, WPA2_AUTH_FT_PSK = 0x0e, + WPA3_AUTH_OWE = 0x0f, WPA2_AUTH_INVALID }; @@ -134,6 +135,8 @@ 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); + uint8_t *(*owe_build_dhie)(uint16_t group); + int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len); }; struct wpa2_funcs { @@ -239,7 +242,7 @@ int esp_wifi_ipc_internal(wifi_ipc_config_t *cfg, bool sync); int esp_wifi_register_wpa2_cb_internal(struct wpa2_funcs *cb); int esp_wifi_unregister_wpa2_cb_internal(void); bool esp_wifi_sta_prof_is_wpa2_internal(void); -bool esp_wifi_sta_prof_is_wpa3_internal(void); +bool esp_wifi_sta_prof_is_rsn_internal(void); bool esp_wifi_sta_prof_is_wapi_internal(void); esp_err_t esp_wifi_sta_wpa2_ent_disable_internal(wifi_wpa2_param_t *param); esp_err_t esp_wifi_sta_wpa2_ent_enable_internal(wifi_wpa2_param_t *param); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index af93891300..1dd5592e9f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -30,6 +30,7 @@ #include "esp_wpa3_i.h" #include "esp_wpa2.h" #include "esp_common_i.h" +#include "esp_owe_i.h" #include "esp_wps.h" #include "eap_server/eap.h" @@ -83,7 +84,7 @@ int wpa_config_profile(uint8_t *bssid) if (esp_wifi_sta_prof_is_wpa_internal()) { wpa_set_profile(WPA_PROTO_WPA, esp_wifi_sta_get_prof_authmode_internal()); - } else if (esp_wifi_sta_prof_is_wpa2_internal() || esp_wifi_sta_prof_is_wpa3_internal()) { + } else if (esp_wifi_sta_prof_is_rsn_internal()) { wpa_set_profile(WPA_PROTO_RSN, esp_wifi_sta_get_prof_authmode_internal()); } else if (esp_wifi_sta_prof_is_wapi_internal()) { wpa_set_profile(WPA_PROTO_WAPI, esp_wifi_sta_get_prof_authmode_internal()); @@ -242,6 +243,9 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code) default: break; } +#ifdef CONFIG_OWE_STA + owe_deinit(); +#endif /* CONFIG_OWE_STA */ } #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT @@ -339,6 +343,9 @@ int esp_supplicant_init(void) wpa_cb->wpa_config_done = wpa_config_done; esp_wifi_register_wpa3_cb(wpa_cb); +#ifdef CONFIG_OWE_STA + esp_wifi_register_owe_cb(wpa_cb); +#endif /* CONFIG_OWE_STA */ eloop_init(); ret = esp_supplicant_common_init(wpa_cb); diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index 0c33546957..b6ad56a465 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -47,6 +47,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_OSEN BIT(15) #define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) #define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17) +#define WPA_KEY_MGMT_OWE BIT(22) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { @@ -87,7 +88,8 @@ static inline int wpa_key_mgmt_sha256(int akm) WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_OSEN | WPA_KEY_MGMT_SAE | - WPA_KEY_MGMT_IEEE8021X_SUITE_B)); + WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_OWE)); } static inline int wpa_key_mgmt_sha384(int akm) @@ -101,11 +103,17 @@ static inline int wpa_key_mgmt_suite_b(int akm) WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); } +static inline int wpa_key_mgmt_owe(int akm) +{ + return akm == WPA_KEY_MGMT_OWE; +} + static inline int wpa_key_mgmt_wpa(int akm) { return wpa_key_mgmt_wpa_ieee8021x(akm) || wpa_key_mgmt_wpa_psk(akm) || - wpa_key_mgmt_sae(akm); + wpa_key_mgmt_sae(akm) || + wpa_key_mgmt_owe(akm); } static inline int wpa_key_mgmt_wpa_any(int akm) diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 4dc35cf68e..34d3c73756 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -324,6 +324,11 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) return WPA_KEY_MGMT_SAE; #endif /* CONFIG_WPA3_SAE */ +#ifdef CONFIG_OWE_STA + if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) + return WPA_KEY_MGMT_OWE; +#endif /* CONFIG_OWE_STA */ + return 0; } @@ -853,7 +858,7 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: if (hmac_sha1(key, key_len, buf, len, hash)) return -1; - memcpy(mic, hash, MD5_MAC_LEN); + os_memcpy(mic, hash, MD5_MAC_LEN); break; case WPA_KEY_INFO_TYPE_AES_128_CMAC: return omac1_aes_128(key, buf, len, mic); @@ -878,7 +883,23 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, os_memcpy(mic, hash, 24); break; #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_OWE_STA + case WPA_KEY_MGMT_OWE: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)", + (unsigned int) key_len * 8 * 2); + if (key_len == 128 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else { + wpa_printf(MSG_INFO,"OWE: Unsupported KCK length: %u", + (unsigned int) key_len); + return -1; + } + os_memcpy(mic, hash, key_len); + break; +#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_IEEE80211W */ default: return -1; @@ -1051,6 +1072,10 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *nonce1, const u8 *nonce2, struct wpa_ptk *ptk, int akmp, int cipher) { + if (pmk_len == 0) { + wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation"); + return -1; + } u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index d4772b9137..f232f73cf1 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -66,6 +66,8 @@ #define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) +#define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18) + #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) diff --git a/components/wpa_supplicant/src/crypto/crypto.h b/components/wpa_supplicant/src/crypto/crypto.h index 9a43c9bfd9..8c6c0a1c74 100644 --- a/components/wpa_supplicant/src/crypto/crypto.h +++ b/components/wpa_supplicant/src/crypto/crypto.h @@ -20,6 +20,7 @@ #ifndef CRYPTO_H #define CRYPTO_H +#include "utils/common.h" /** * md4_vector - MD4 hash for data vector @@ -1081,4 +1082,15 @@ int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, */ int crypto_bignum_to_string(const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen); + +struct crypto_ecdh; + +void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); + +struct crypto_ecdh * crypto_ecdh_init(int group); + +struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh,int y); +struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, + const u8 *key, size_t len); + #endif /* CRYPTO_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 9a54919d33..ba9986e80c 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -29,9 +29,11 @@ #include "crypto/sha1.h" #include "crypto/aes_wrap.h" #include "crypto/ccmp.h" +#include "crypto/sha256.h" #include "esp_rom_sys.h" #include "common/bss.h" #include "esp_common_i.h" +#include "esp_owe_i.h" /** * eapol_sm_notify_eap_success - Notification of external EAP success trigger @@ -284,7 +286,7 @@ static 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_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else if (sm->key_mgmt == WPA_KEY_MGMT_SAE) + else if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE) ver = 0; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -807,7 +809,7 @@ void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) + if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_OWE) eapol_sm_notify_eap_success(TRUE); /* * Start preauthentication after a short wait to avoid a @@ -1719,7 +1721,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || sm->key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->key_mgmt) || - sm->key_mgmt == WPA_KEY_MGMT_SAE) { + sm->key_mgmt == WPA_KEY_MGMT_SAE || + sm->key_mgmt == WPA_KEY_MGMT_OWE) { u8 *buf; if (*key_data_len < 8 || *key_data_len % 8) { #ifdef DEBUG_PRINT @@ -1912,6 +1915,9 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) sm->key_mgmt != WPA_KEY_MGMT_SAE && #endif !wpa_key_mgmt_suite_b(sm->key_mgmt) && +#ifdef CONFIG_OWE_STA + sm->key_mgmt != WPA_KEY_MGMT_OWE && +#endif /* CONFIG_OWE_STA */ #endif ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { #ifdef DEBUG_PRINT @@ -1933,7 +1939,8 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && sm->key_mgmt != WPA_KEY_MGMT_OSEN && !wpa_key_mgmt_suite_b(sm->key_mgmt) && - sm->key_mgmt != WPA_KEY_MGMT_SAE) { + sm->key_mgmt != WPA_KEY_MGMT_SAE && + sm->key_mgmt != WPA_KEY_MGMT_OWE) { goto out; } } else @@ -1942,7 +1949,8 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) if (sm->pairwise_cipher == WPA_CIPHER_CCMP && !wpa_key_mgmt_suite_b(sm->key_mgmt) && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES && - sm->key_mgmt != WPA_KEY_MGMT_SAE) { + sm->key_mgmt != WPA_KEY_MGMT_SAE && + sm->key_mgmt != WPA_KEY_MGMT_OWE) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key " "descriptor version (%d) is not 2.", ver); @@ -2223,6 +2231,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; } else if (auth_mode == WPA2_AUTH_FT_PSK) { sm->key_mgmt = WPA_KEY_MGMT_FT_PSK; + } else if (auth_mode == WPA3_AUTH_OWE) { + sm->key_mgmt = WPA_KEY_MGMT_OWE; } else { sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */ } @@ -2274,6 +2284,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, sm->ap_notify_completed_rsne = esp_wifi_sta_is_ap_notify_completed_rsne_internal(); if (sm->key_mgmt == WPA_KEY_MGMT_SAE || + sm->key_mgmt == WPA_KEY_MGMT_OWE || is_wpa2_enterprise_connection()) { if (!esp_wifi_skip_supp_pmkcaching() && use_pmk_cache) { pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, 0); @@ -2374,7 +2385,7 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) * Here only handle passphrase string. Need extra step to handle 32B, 64Hex raw * PMK. */ - if (sm->key_mgmt == WPA_KEY_MGMT_SAE) + if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE) return; /* This is really SLOW, so just re cacl while reset param */ @@ -2595,4 +2606,190 @@ void wpa_sta_clear_curr_pmksa(void) { pmksa_cache_clear_current(sm); } +struct wpa_sm * get_wpa_sm(void) +{ + return &gWpaSm; +} + +#ifdef CONFIG_OWE_STA +struct wpabuf *owe_build_assoc_req(struct wpa_sm *sm, u16 group) +{ + struct wpabuf *owe_ie = NULL, *pub = NULL; + size_t prime_len; + + if (group == OWE_DH_GRP19) { + prime_len = OWE_PRIME_LEN; + } else { + wpa_printf(MSG_ERROR, "OWE: Unsupported Diffie-Hellman group"); + return NULL; + } + + sm->owe_ecdh = crypto_ecdh_init(group); + + if (!sm->owe_ecdh) { + wpa_printf(MSG_ERROR, "Initialization of ecdh failed"); + return NULL; + } + + sm->owe_group = group; + /* Get own public key */ + pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0); + pub = wpabuf_zeropad(pub, prime_len); + + if (!pub) { + wpa_printf(MSG_ERROR, "Own public key is NULL"); + goto fail; + } + + wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); + owe_ie = wpabuf_alloc(5 + wpabuf_len(pub)); + + if (!owe_ie) { + wpa_printf(MSG_ERROR, "OWE IE allocation failed"); + goto fail; + } + + /* Constructing the DH IE */ + wpabuf_put_u8(owe_ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(owe_ie, 1 + 2 + wpabuf_len(pub)); + wpabuf_put_u8(owe_ie, WLAN_EID_EXT_OWE_DH_PARAM); + wpabuf_put_le16(owe_ie, group); + wpabuf_put_buf(owe_ie, pub); + wpabuf_free(pub); + + wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element", owe_ie); + + return (struct wpabuf *)wpabuf_head(owe_ie); + +fail: + wpabuf_free(pub); + crypto_ecdh_deinit(sm->owe_ecdh); + return NULL; +} + +int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len) +{ + size_t prime_len=0,hash_len=0; + struct wpabuf * sh_secret = NULL, *pub = NULL, *hkey = NULL; + int res; + const char *info = "OWE Key Generation"; + u8 pmkid[SHA256_MAC_LEN], prk[SHA256_MAC_LEN], pmk[SHA256_MAC_LEN]; + const u8 *addr[2]; + size_t len[2]; + u16 group; + + struct wpa_sm *sm; + sm = get_wpa_sm(); + + (void)res; + struct wpa_ie_data *parsed_rsn_data; + parsed_rsn_data = os_zalloc(sizeof(struct wpa_ie_data)); + if (!parsed_rsn_data) { + wpa_printf(MSG_ERROR, "Memory allocation failed"); + goto fail; + } + + if (rsn_ie && rsn_len && wpa_parse_wpa_ie_rsn(rsn_ie, rsn_len + 2, parsed_rsn_data) != 0) { + goto fail; + } + if (!dh_ie && !dh_len && parsed_rsn_data->num_pmkid == 0) { + wpa_printf(MSG_ERROR, "OWE: No diffie hellman parameter in response"); + goto fail; + } + + if (!sm->cur_pmksa) { /* No PMK caching */ + dh_len += 2; + + dh_ie += 3; + dh_len -=3; + group = WPA_GET_LE16(dh_ie); + + /* Only group 19 is supported */ + if ((group != sm->owe_group) || (group != OWE_DH_GRP19)) { + wpa_printf(MSG_ERROR, "OWE: Unexpected Diffie-Hellman group in response"); + goto fail; + } + + prime_len = OWE_PRIME_LEN; + + /* Set peer's public key point and calculate shared secret */ + sh_secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0, dh_ie+2, dh_len-2); + sh_secret = wpabuf_zeropad(sh_secret, prime_len); + if (!sh_secret) { + wpa_printf(MSG_ERROR, "OWE: Invalid peer DH public key"); + goto fail; + } + + wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", sh_secret); + pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0); + if (!pub) { + wpa_printf(MSG_ERROR, "No own public key"); + wpabuf_free(sh_secret); + goto fail; + } + + /* PMKID = Truncate-128(Hash(C | A)) */ + addr[0] = wpabuf_head(pub); + len[0] = wpabuf_len(pub); + addr[1] = dh_ie + 2; + len[1] = dh_len - 2; + + res = sha256_vector(2, addr, len, pmkid); + hash_len = SHA256_MAC_LEN; + + pub = wpabuf_zeropad(pub, prime_len); + + /* prk = HKDF-extract(C | A | group, z) */ + hkey = wpabuf_alloc(wpabuf_len(pub) + dh_len - 2 + 2); + + wpabuf_put_buf(hkey, pub); /* C */ + wpabuf_free(pub); + + wpabuf_put_data(hkey, dh_ie + 2, dh_len - 2); /* A */ + wpabuf_put_le16(hkey, sm->owe_group); /* group */ + + res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), wpabuf_head(sh_secret), wpabuf_len(sh_secret), prk); + hash_len = SHA256_MAC_LEN; + + wpabuf_free(hkey); + wpabuf_free(sh_secret); + + wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len); + + /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */ + res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *)info, + os_strlen(info), pmk, hash_len); + + forced_memzero(prk, SHA256_MAC_LEN); + wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, OWE_PMKID_LEN); + + os_memcpy(sm->pmk,pmk,hash_len); + sm->pmk_len = hash_len; + wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len); + + pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0, + sm->bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt); + goto done; + } else { /* PMK caching */ + if (parsed_rsn_data && sm->cur_pmksa) { + if (parsed_rsn_data->num_pmkid == 1 && parsed_rsn_data->pmkid) { + if (os_memcmp(parsed_rsn_data->pmkid, sm->cur_pmksa->pmkid, OWE_PMKID_LEN) == 0) { + wpa_printf(MSG_DEBUG, "OWE: Using PMK caching"); + wpa_sm_set_pmk_from_pmksa(sm); + goto done; + } else { + wpa_printf(MSG_DEBUG, "OWE : Invalid PMKID in response"); + goto fail; + } + } + } + } +done: + os_free(parsed_rsn_data); + return 0; +fail: + os_free(parsed_rsn_data); + return -1; +} +#endif // CONFIG_OWE_STA #endif // ESP_SUPPLICANT diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 8ba7a76806..ddb15a328a 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -115,4 +115,12 @@ wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, } #endif /* CONFIG_IEEE80211R */ +struct wpa_sm * get_wpa_sm(void); + +void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); + +int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len); + +struct wpabuf *owe_build_assoc_req(struct wpa_sm *sm, u16 group); + #endif /* WPA_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 30a09ba8be..da55b32081 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -109,6 +109,10 @@ struct wpa_sm { u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */ size_t assoc_resp_ies_len; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_OWE_STA + struct crypto_ecdh *owe_ecdh; + u16 owe_group; +#endif /* CONFIG_OWE_STA */ }; /** diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index a456edc9f1..341beb837a 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -197,6 +197,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } else if (key_mgmt == WPA_KEY_MGMT_SAE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); #endif /* CONFIG_WPA3_SAE */ +#ifdef CONFIG_OWE_STA + } else if (key_mgmt == WPA_KEY_MGMT_OWE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); +#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_IEEE80211W */ } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); @@ -214,7 +218,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, #ifdef CONFIG_IEEE80211W if (sm->pmf_cfg.capable) { capab |= WPA_CAPABILITY_MFPC; - if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE) { + if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE || key_mgmt == WPA_KEY_MGMT_OWE) { capab |= WPA_CAPABILITY_MFPR; } } diff --git a/components/wpa_supplicant/src/utils/common.h b/components/wpa_supplicant/src/utils/common.h index 05e2f11b28..31fa00a0d4 100644 --- a/components/wpa_supplicant/src/utils/common.h +++ b/components/wpa_supplicant/src/utils/common.h @@ -474,5 +474,6 @@ void * __hide_aliasing_typecast(void *foo); #endif /* CONFIG_VALGRIND */ #define IANA_SECP256R1 19 - +#define IANA_SECP384R1 20 +#define IANA_SECP521R1 21 #endif /* COMMON_H */ diff --git a/examples/wifi/scan/main/scan.c b/examples/wifi/scan/main/scan.c index 34b88a24ff..3461e3525d 100644 --- a/examples/wifi/scan/main/scan.c +++ b/examples/wifi/scan/main/scan.c @@ -28,6 +28,9 @@ static void print_auth_mode(int authmode) case WIFI_AUTH_OPEN: ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN"); break; + case WIFI_AUTH_OWE: + ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OWE"); + break; case WIFI_AUTH_WEP: ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP"); break;