diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_eap_client.h b/components/wpa_supplicant/esp_supplicant/include/esp_eap_client.h index cb0d7aa11b..3827663e08 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_eap_client.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_eap_client.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -320,28 +320,20 @@ esp_err_t esp_eap_client_set_fast_params(esp_eap_fast_config config); esp_err_t esp_eap_client_use_default_cert_bundle(bool use_default_bundle); /** - * @brief Set name for certificate domain name validation + * This function sets the expected domain name for validating the certificate's subject name. + * If the provided domain name does not match the certificate's subject name, validation will fail. * - * Enabling this option will only accept certificate with the provided subject name + * @attention 1. The `domain_name` should be a NULL-terminated string. * - * @param[in] domain_match The expected domain name - * @param[in] len Length of the domain name (limited to 1~127 bytes). + * @param[in] domain_name The expected domain name. Pass `NULL` to clear the domain matching. * * @return - * - ESP_OK: The identity was set successfully. - * - ESP_ERR_INVALID_ARG: Invalid argument (len <= 0 or len >= 128). + * - ESP_OK: The domain match was set successfully. + * - ESP_ERR_INVALID_ARG: Invalid argument (length > 255). * - ESP_ERR_NO_MEM: Memory allocation failure. + * - ESP_ERR_NOT_SUPPORTED: Feature not supported. */ -esp_err_t esp_eap_client_set_domain_match(const char *domain_match); - -/** - * @brief Clear the domain name for certificate validation - * - * This function clears the domain name that was previously set for the EAP client. - * After calling this function, the EAP client will no longer use the previously - * configured domain name during the authentication process. - */ -void esp_eap_client_clear_domain_match(void); +esp_err_t esp_eap_client_set_domain_name(const char *domain_name); #ifdef __cplusplus } diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index cc3910dcde..803bcc74af 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -520,18 +520,18 @@ static int set_client_config(const struct tls_connection_params *cfg, tls_contex } } - /* Usages of default ciphersuites can take a lot of time on low end device - * and can cause watchdog. Enabling the ciphers which are secured enough - * but doesn't take that much processing power */ + /* The use of default ciphersuites may take a lot of time on low-end devices + * and may trigger the watchdog timer. Enable ciphers that are secure enough + * but require less processing power. */ tls_set_ciphersuite(cfg, tls); #ifdef CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK mbedtls_ssl_set_verify(&tls->ssl, tls_disable_key_usages, NULL); #endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/ - - if (cfg->domain_match) { - mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_set_hostname(&tls->ssl, cfg->domain_match); + ret = mbedtls_ssl_set_hostname(&tls->ssl, cfg->domain_match); + if (ret != 0) { + wpa_printf(MSG_ERROR, "Failed to set hostname"); + return ret; } #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_eap_client.c b/components/wpa_supplicant/esp_supplicant/src/esp_eap_client.c index dcbdc3598a..a788ab5a23 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_eap_client.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_eap_client.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -932,6 +932,9 @@ esp_err_t esp_eap_client_set_ca_cert(const unsigned char *ca_cert, int ca_cert_l g_wpa_ca_cert_len = ca_cert_len; } + /* CA certs Set/updated, flushing current PMK cache */ + wpa_sm_pmksa_cache_flush(get_wpa_sm(), NULL); + return ESP_OK; } @@ -1192,32 +1195,36 @@ esp_err_t esp_eap_client_use_default_cert_bundle(bool use_default_bundle) #endif } -#define MAX_DOMAIN_MATCH_LEN 128 -esp_err_t esp_eap_client_set_domain_match(const char *domain_match) +#define MAX_DOMAIN_MATCH_LEN 255 /* Maximum host name defined in RFC 1035 */ +esp_err_t esp_eap_client_set_domain_name(const char *domain_name) { +#ifdef CONFIG_TLS_INTERNAL_CLIENT + return ESP_ERR_NOT_SUPPORTED; +#else + int len = domain_name ? os_strnlen(domain_name, MAX_DOMAIN_MATCH_LEN + 1) : 0; + if (len > MAX_DOMAIN_MATCH_LEN) { + return ESP_ERR_INVALID_ARG; + } + if (g_wpa_domain_match && domain_name && os_strcmp(g_wpa_domain_match, domain_name) == 0) { + return ESP_OK; + } if (g_wpa_domain_match) { os_free(g_wpa_domain_match); g_wpa_domain_match = NULL; } - int len = os_strlen(domain_match); - if (len > MAX_DOMAIN_MATCH_LEN) { - return ESP_ERR_INVALID_ARG; + if (!domain_name) { + return ESP_OK; } - g_wpa_domain_match = (char *)os_zalloc(len+1); - if (g_wpa_domain_match == NULL) { + g_wpa_domain_match = os_strdup(domain_name); + if (!g_wpa_domain_match) { return ESP_ERR_NO_MEM; } - os_strlcpy(g_wpa_domain_match, domain_match, len+1); + /* flushing the PMK only needed when going for a better security ie no-domain name to domain name + * or changing the domain name */ + wpa_sm_pmksa_cache_flush(get_wpa_sm(), NULL); return ESP_OK; +#endif } - -void esp_eap_client_clear_domain_match(void) -{ - if (g_wpa_domain_match) { - os_free(g_wpa_domain_match); - } - g_wpa_domain_match = NULL; -} \ No newline at end of file diff --git a/components/wpa_supplicant/port/include/os.h b/components/wpa_supplicant/port/include/os.h index 2c6e594049..3ed465b3ae 100644 --- a/components/wpa_supplicant/port/include/os.h +++ b/components/wpa_supplicant/port/include/os.h @@ -260,6 +260,9 @@ char * ets_strdup(const char *s); #ifndef os_strlen #define os_strlen(s) strlen(s) #endif +#ifndef os_strnlen +#define os_strnlen(s, n) strnlen((s), (n)) +#endif #ifndef os_strcasecmp #ifdef _MSC_VER #define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) diff --git a/components/wpa_supplicant/src/eap_peer/eap.c b/components/wpa_supplicant/src/eap_peer/eap.c index 2c35952a5a..c06268c608 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.c +++ b/components/wpa_supplicant/src/eap_peer/eap.c @@ -67,7 +67,9 @@ bool g_wpa_suiteb_certification; bool g_wpa_default_cert_bundle; int (*esp_crt_bundle_attach_fn)(void *conf); #endif +#ifndef CONFIG_TLS_INTERNAL_CLIENT char *g_wpa_domain_match; +#endif void eap_peer_config_deinit(struct eap_sm *sm); void eap_peer_blob_deinit(struct eap_sm *sm); @@ -530,7 +532,9 @@ int eap_peer_config_init( sm->config.identity = NULL; sm->config.password = NULL; sm->config.new_password = NULL; +#ifndef CONFIG_TLS_INTERNAL_CLIENT sm->config.domain_match = g_wpa_domain_match; +#endif sm->config.private_key_passwd = private_key_passwd; sm->config.client_cert = (u8 *)sm->blob[0].name; sm->config.private_key = (u8 *)sm->blob[1].name; @@ -593,7 +597,6 @@ int eap_peer_config_init( sm->config.flags |= TLS_CONN_USE_DEFAULT_CERT_BUNDLE; } #endif - /* To be used only for EAP-FAST */ if (g_wpa_phase1_options) { sm->config.phase1 = g_wpa_phase1_options; diff --git a/components/wpa_supplicant/src/eap_peer/eap.h b/components/wpa_supplicant/src/eap_peer/eap.h index a11198d78c..93d623d1cc 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.h +++ b/components/wpa_supplicant/src/eap_peer/eap.h @@ -49,7 +49,9 @@ extern bool g_wpa_suiteb_certification; extern bool g_wpa_default_cert_bundle; extern int (*esp_crt_bundle_attach_fn)(void *conf); +#ifndef CONFIG_TLS_INTERNAL_CLIENT extern char *g_wpa_domain_match; +#endif const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len); void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); diff --git a/examples/wifi/wifi_enterprise/main/Kconfig.projbuild b/examples/wifi/wifi_enterprise/main/Kconfig.projbuild index aedbb0db0d..0e5e606b33 100644 --- a/examples/wifi/wifi_enterprise/main/Kconfig.projbuild +++ b/examples/wifi/wifi_enterprise/main/Kconfig.projbuild @@ -100,15 +100,18 @@ menu "Example Configuration" help Use default CA certificate bundle for WiFi enterprise connection - config EXAMPLE_USE_SERVER_DOMAIN_MATCH - bool "Validate server cert domain" + config EXAMPLE_VALIDATE_SERVER_CERT_DOMAIN + bool "Enable server certificate domain validation" + depends on EXAMPLE_VALIDATE_SERVER_CERT + default n help - Validate the certificate domain + Enable validation of the server certificate's domain name. - config EXAMPLE_SERVER_DOMAIN_MATCH_VALUE - string "Server cert domain" - depends on EXAMPLE_USE_SERVER_DOMAIN_MATCH + config EXAMPLE_SERVER_CERT_DOMAIN + string "Expected server certificate domain" + depends on EXAMPLE_VALIDATE_SERVER_CERT_DOMAIN default "espressif.com" help - Accept only server certificates matching this domain + Specify the expected domain name for the server certificate. + The connection will be accepted only if the server certificate matches this domain. endmenu diff --git a/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c b/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c index 710b0abac4..a1ebb65e1d 100644 --- a/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c +++ b/examples/wifi/wifi_enterprise/main/wifi_enterprise_main.c @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: 2006-2016 ARM Limited - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +33,7 @@ #define EXAMPLE_EAP_ID CONFIG_EXAMPLE_EAP_ID #define EXAMPLE_EAP_USERNAME CONFIG_EXAMPLE_EAP_USERNAME #define EXAMPLE_EAP_PASSWORD CONFIG_EXAMPLE_EAP_PASSWORD +#define EXAMPLE_SERVER_CERT_DOMAIN CONFIG_EXAMPLE_SERVER_CERT_DOMAIN /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -156,8 +157,8 @@ static void initialise_wifi(void) #ifdef CONFIG_EXAMPLE_USE_DEFAULT_CERT_BUNDLE ESP_ERROR_CHECK(esp_eap_client_use_default_cert_bundle(true)); #endif -#ifdef CONFIG_EXAMPLE_USE_SERVER_DOMAIN_MATCH - ESP_ERROR_CHECK(esp_eap_client_set_domain_match(CONFIG_EXAMPLE_SERVER_DOMAIN_MATCH_VALUE)); +#ifdef CONFIG_EXAMPLE_VALIDATE_SERVER_CERT_DOMAIN + ESP_ERROR_CHECK(esp_eap_client_set_domain_name(EXAMPLE_SERVER_CERT_DOMAIN)); #endif ESP_ERROR_CHECK(esp_wifi_sta_enterprise_enable()); ESP_ERROR_CHECK(esp_wifi_start());