From d31654da968c979f0b652ee1879f49151aa4891a Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 25 Dec 2024 18:24:34 +0800 Subject: [PATCH] fix(esp-tls): Fixed the server session create API Added the option to define tls_handshake_timeout value for the esp_tls_server_session_create API. At the moment, the API gets stuck infinitely if the handshake is blocked on recieving more data and the peer connection has closed due to some issue. Closes https://github.com/espressif/esp-idf/issues/14999 --- components/esp-tls/esp_tls.h | 4 ++++ components/esp-tls/esp_tls_errors.h | 2 +- components/esp-tls/esp_tls_mbedtls.c | 17 ++++++++++++++++- .../esp-tls/private_include/esp_tls_private.h | 2 ++ components/esp_common/src/esp_err_to_name.c | 3 +++ .../esp_https_server/include/esp_https_server.h | 4 ++++ components/esp_https_server/src/https_server.c | 1 + 7 files changed, 31 insertions(+), 2 deletions(-) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index a846341bc2..c29039f9aa 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -307,6 +307,10 @@ typedef struct esp_tls_cfg_server { bool use_secure_element; /*!< Enable this option to use secure element or atecc608a chip */ + uint32_t tls_handshake_timeout_ms; /*!< TLS handshake timeout in milliseconds. + Note: If this value is not set, by default the timeout is + set to 10 seconds. If you wish that the session should wait + indefinitely then please use a larger value e.g., INT32_MAX */ #if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS) esp_tls_server_session_ticket_ctx_t * ticket_ctx; /*!< Session ticket generation context. diff --git a/components/esp-tls/esp_tls_errors.h b/components/esp-tls/esp_tls_errors.h index 6606562671..9f6ee286c7 100644 --- a/components/esp-tls/esp_tls_errors.h +++ b/components/esp-tls/esp_tls_errors.h @@ -32,7 +32,7 @@ extern "C" { #define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< new connection in esp_tls_low_level_conn connection timeouted */ #define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*< esp-tls use Secure Element returned failed */ #define ESP_ERR_ESP_TLS_TCP_CLOSED_FIN (ESP_ERR_ESP_TLS_BASE + 0x08) /*< esp-tls's TPC transport connection has benn closed (in a clean way) */ - +#define ESP_ERR_ESP_TLS_SERVER_HANDSHAKE_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< TLS handshake timeout */ /* mbedtls specific error codes */ #define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls parse certificates was partly successful */ #define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned error */ diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 40898314a1..bf6c530d16 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.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 */ @@ -16,6 +16,7 @@ #include "esp_tls_mbedtls.h" #include "esp_tls_private.h" #include "esp_tls_error_capture_internal.h" +#include "esp_tls_platform_port.h" #include #include "esp_log.h" #include "esp_check.h" @@ -928,10 +929,24 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp if ((ret = esp_mbedtls_server_session_init(cfg, sockfd, tls)) != 0) { return ret; } + + uint64_t timeout_ms; + if (cfg->tls_handshake_timeout_ms == 0) { + timeout_ms = ESP_TLS_DEFAULT_SERVER_HANDSHAKE_TIMEOUT_MS; + } else { + timeout_ms = cfg->tls_handshake_timeout_ms; + } + uint64_t start_time = esp_tls_get_platform_time(); + while ((ret = esp_mbedtls_server_session_continue_async(tls)) != 0) { if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) { return ret; } + uint64_t elapsed_time_us = esp_tls_get_platform_time() - start_time; + if ((elapsed_time_us / 1000) > timeout_ms) { + ESP_LOGD(TAG, "Server handshake timed out"); + return ESP_ERR_ESP_TLS_SERVER_HANDSHAKE_TIMEOUT; + } } return ret; } diff --git a/components/esp-tls/private_include/esp_tls_private.h b/components/esp-tls/private_include/esp_tls_private.h index 4341557aaf..669e01aad6 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -103,3 +103,5 @@ typedef esp_err_t (*set_server_config_func_ptr) (esp_tls_cfg_server_t *cfg, esp_ typedef struct esp_tls_server_params { set_server_config_func_ptr set_server_cfg; } esp_tls_server_params_t; + +#define ESP_TLS_DEFAULT_SERVER_HANDSHAKE_TIMEOUT_MS (10000) /*!< Default handshake timeout in milliseconds */ diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index bf4c3b7d7e..1c342e6b2a 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -694,6 +694,9 @@ static const esp_err_msg_t esp_err_msg_table[] = { # ifdef ESP_ERR_ESP_TLS_TCP_CLOSED_FIN ERR_TBL_IT(ESP_ERR_ESP_TLS_TCP_CLOSED_FIN), /* 32776 0x8008 */ # endif +# ifdef ESP_ERR_ESP_TLS_SERVER_HANDSHAKE_TIMEOUT + ERR_TBL_IT(ESP_ERR_ESP_TLS_SERVER_HANDSHAKE_TIMEOUT), /* 32777 0x8009 TLS handshake timeout */ +# endif # ifdef ESP_ERR_MBEDTLS_CERT_PARTLY_OK ERR_TBL_IT(ESP_ERR_MBEDTLS_CERT_PARTLY_OK), /* 32784 0x8010 mbedtls parse certificates was partly successful */ # endif diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 56f19edca7..3c63cdf2b3 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -132,6 +132,9 @@ struct httpd_ssl_config { * Used for negotiating during the TLS handshake, first one the client supports is selected. * The data structure must live as long as the https server itself */ const char** alpn_protos; + + /** TLS handshake timeout in milliseconds, default timeout is 10 seconds if not set */ + uint32_t tls_handshake_timeout_ms; }; typedef struct httpd_ssl_config httpd_ssl_config_t; @@ -190,6 +193,7 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; .ssl_userdata = NULL, \ .cert_select_cb = NULL, \ .alpn_protos = NULL, \ + .tls_handshake_timeout_ms = 0 \ } /** diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index ed3d432a94..b3d22e5346 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -277,6 +277,7 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht cfg->userdata = config->ssl_userdata; cfg->alpn_protos = config->alpn_protos; + cfg->tls_handshake_timeout_ms = config->tls_handshake_timeout_ms; #if defined(CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK) cfg->cert_select_cb = config->cert_select_cb;