diff --git a/components/esp-tls/private_include/esp_tls_private.h b/components/esp-tls/private_include/esp_tls_private.h index e42407bd20..a90e5a26ec 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -6,10 +6,6 @@ #pragma once -/** - * @brief ESP-TLS Connection Handle - */ - #include #include #include @@ -23,12 +19,15 @@ #include "mbedtls/error.h" #ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS #include "mbedtls/ssl_ticket.h" -#endif +#endif /* CONFIG_ESP_TLS_SERVER_SESSION_TICKETS */ #ifdef CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 #include "psa/crypto.h" -#endif -#endif +#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ +/** + * @brief ESP-TLS Connection Handle + */ struct esp_tls { #ifdef CONFIG_ESP_TLS_USING_MBEDTLS mbedtls_ssl_context ssl; /*!< TLS/SSL context */ diff --git a/components/esp_http_client/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt index fb93315879..4a353e33ca 100644 --- a/components/esp_http_client/CMakeLists.txt +++ b/components/esp_http_client/CMakeLists.txt @@ -4,17 +4,10 @@ else() set(req linux esp_event) endif() -if(CONFIG_ESP_HTTP_CLIENT_PSA_CRYPTO_MIGRATE) - set(HTTP_CRYPTO_SRC "lib/http_crypto_psa.c") -else() - set(HTTP_CRYPTO_SRC "lib/http_crypto_mbedtls.c") -endif() - idf_component_register(SRCS "esp_http_client.c" "lib/http_auth.c" "lib/http_header.c" "lib/http_utils.c" - ${HTTP_CRYPTO_SRC} INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "lib/include" # lwip is a public requirement because esp_http_client.h includes sys/socket.h diff --git a/components/esp_http_client/Kconfig b/components/esp_http_client/Kconfig index fcdb0d92c1..3eaaf171c4 100644 --- a/components/esp_http_client/Kconfig +++ b/components/esp_http_client/Kconfig @@ -42,13 +42,6 @@ menu "ESP HTTP client" This config option helps in setting the time in millisecond to wait for event to be posted to the system default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY. - config ESP_HTTP_CLIENT_PSA_CRYPTO_MIGRATE - depends on MBEDTLS_VER_4_X_SUPPORT - bool "Migrate ESP HTTP Client to use PSA Crypto" - default y - help - Migrate ESP HTTP Client to use PSA Crypto. - config ESP_HTTP_CLIENT_SAVE_RESPONSE_HEADERS bool "Save response headers" default n diff --git a/components/esp_http_client/lib/http_auth.c b/components/esp_http_client/lib/http_auth.c index 594b0a6f63..9e5477cd1f 100644 --- a/components/esp_http_client/lib/http_auth.c +++ b/components/esp_http_client/lib/http_auth.c @@ -18,11 +18,12 @@ #include "http_utils.h" #include "http_auth.h" -#include "http_crypto.h" #include "psa/crypto.h" #define MD5_MAX_LEN (33) +#define SHA256_LEN (32) +#define SHA256_HEX_LEN (65) #define HTTP_AUTH_BUF_LEN (1024) static const char *TAG = "HTTP_AUTH"; diff --git a/components/esp_http_client/lib/http_crypto_mbedtls.c b/components/esp_http_client/lib/http_crypto_mbedtls.c deleted file mode 100644 index 62f730fafa..0000000000 --- a/components/esp_http_client/lib/http_crypto_mbedtls.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "http_crypto.h" -#include "esp_rom_md5.h" -#include "esp_err.h" -#include "mbedtls/sha256.h" -#include "esp_log.h" - -static const char *TAG = "http_crypto_mbedtls"; - - -esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash) -{ - if (data == NULL || data_len == 0 || hash == NULL) { - ESP_LOGE(TAG, "Invalid input parameters"); - return ESP_FAIL; - } - - esp_err_t err = ESP_FAIL; - mbedtls_sha256_context ctx; - mbedtls_sha256_init(&ctx); - - if (mbedtls_sha256_starts(&ctx, false) != 0) { - ESP_LOGE(TAG, "Failed to start SHA-256 hash"); - goto exit; - } - - if (mbedtls_sha256_update(&ctx, data, data_len) != 0) { - ESP_LOGE(TAG, "Failed to update SHA-256 hash"); - goto exit; - } - - if (mbedtls_sha256_finish(&ctx, hash) != 0) { - ESP_LOGE(TAG, "Failed to finish SHA-256 hash"); - goto exit; - } - - err = ESP_OK; - -exit: - mbedtls_sha256_free(&ctx); - return err; -} diff --git a/components/esp_http_client/lib/http_crypto_psa.c b/components/esp_http_client/lib/http_crypto_psa.c deleted file mode 100644 index 8866b2694c..0000000000 --- a/components/esp_http_client/lib/http_crypto_psa.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include "esp_err.h" -#include "http_crypto.h" -#include "psa/crypto.h" -#include "esp_log.h" - -static const char *TAG = "http_crypto_psa"; - -esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash) -{ - if (data == NULL || data_len == 0 || hash == NULL) { - ESP_LOGE(TAG, "Invalid input parameters"); - return ESP_FAIL; - } - - size_t hash_len = 0; - psa_status_t status = psa_hash_compute(PSA_ALG_SHA_256, data, data_len, hash, SHA256_LEN, &hash_len); - if (status != PSA_SUCCESS || hash_len != SHA256_LEN) { - ESP_LOGE(TAG, "Failed to compute SHA-256 hash"); - return ESP_FAIL; - } - return ESP_OK; -} diff --git a/components/esp_http_client/lib/include/http_crypto.h b/components/esp_http_client/lib/include/http_crypto.h deleted file mode 100644 index 53edfa0468..0000000000 --- a/components/esp_http_client/lib/include/http_crypto.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "esp_err.h" - - -#define SHA256_LEN (32) -#define SHA256_HEX_LEN (65) - -esp_err_t http_crypto_sha256(const uint8_t *data, size_t data_len, uint8_t *hash); - -#ifdef __cplusplus -} -#endif diff --git a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c b/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c index c101f4e30c..3973b9a068 100644 --- a/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c +++ b/components/mbedtls/port/dynamic/esp_mbedtls_dynamic_impl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -407,6 +407,18 @@ int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl) in_msglen = ssl->MBEDTLS_PRIVATE(in_msglen); buffer_len = tx_buffer_len(ssl, in_msglen); +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* For TLS 1.3 ENCRYPTED_EXTENSIONS state, allocate max size buffer. + * This is needed because ChangeCipherSpec (1 byte) arrives first, + * followed immediately by EncryptedExtensions (potentially large). + * Since mbedtls processes both in the same read loop without returning + * to the wrapper, we need to allocate sufficient space upfront. */ + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_ENCRYPTED_EXTENSIONS) { + buffer_len = tx_buffer_len(ssl, MBEDTLS_SSL_IN_CONTENT_LEN); + ESP_LOGV(TAG, "TLS 1.3 ENCRYPTED_EXTENSIONS: allocating max buffer %d bytes", buffer_len); + } +#endif + ESP_LOGV(TAG, "message length is %d RX buffer length should be %d left is %d", (int)in_msglen, (int)buffer_len, (int)ssl->MBEDTLS_PRIVATE(in_left)); diff --git a/components/mbedtls/port/dynamic/esp_ssl_cli.c b/components/mbedtls/port/dynamic/esp_ssl_cli.c index f7aacca85e..06e51aea73 100644 --- a/components/mbedtls/port/dynamic/esp_ssl_cli.c +++ b/components/mbedtls/port/dynamic/esp_ssl_cli.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,9 +17,9 @@ int __wrap_mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl); static const char *TAG = "SSL client"; -static int manage_resource(mbedtls_ssl_context *ssl, bool add) +static int manage_resource(mbedtls_ssl_context *ssl, bool add, int prev_state) { - int state = add ? ssl->MBEDTLS_PRIVATE(state) : ssl->MBEDTLS_PRIVATE(state) - 1; + int state = add ? ssl->MBEDTLS_PRIVATE(state) : prev_state; if (mbedtls_ssl_is_handshake_over(ssl) || ssl->MBEDTLS_PRIVATE(handshake) == NULL) { return 0; @@ -66,14 +66,20 @@ static int manage_resource(mbedtls_ssl_context *ssl, bool add) if (add) { CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); } else { - CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + /* Don't free RX buffer - TLS 1.3 may have multiple messages in the same record */ + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } } break; case MBEDTLS_SSL_SERVER_CERTIFICATE: if (add) { CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); } else { - CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + /* Don't free RX buffer - TLS 1.3 may have multiple messages in the same record */ + if (!ssl->MBEDTLS_PRIVATE(keep_current_message)) { + CHECK_OK(esp_mbedtls_free_rx_buffer(ssl)); + } #ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT esp_mbedtls_free_cacert(ssl); @@ -149,8 +155,12 @@ static int manage_resource(mbedtls_ssl_context *ssl, bool add) case MBEDTLS_SSL_CERTIFICATE_VERIFY: if (add) { size_t buffer_len = MBEDTLS_SSL_OUT_BUFFER_LEN; - CHECK_OK(esp_mbedtls_add_tx_buffer(ssl, buffer_len)); +#ifdef CONFIG_MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + CHECK_OK(esp_mbedtls_add_rx_buffer(ssl)); + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } else { #ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA esp_mbedtls_free_keycert_key(ssl); @@ -250,33 +260,36 @@ static int manage_resource(mbedtls_ssl_context *ssl, bool add) int __wrap_mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) { - CHECK_OK(manage_resource(ssl, true)); + int prev_state = ssl->MBEDTLS_PRIVATE(state); + CHECK_OK(manage_resource(ssl, true, prev_state)); CHECK_OK(__real_mbedtls_ssl_handshake_client_step(ssl)); - CHECK_OK(manage_resource(ssl, false)); + CHECK_OK(manage_resource(ssl, false, prev_state)); return 0; } int __wrap_mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) { - CHECK_OK(manage_resource(ssl, true)); + int prev_state = ssl->MBEDTLS_PRIVATE(state); + CHECK_OK(manage_resource(ssl, true, prev_state)); CHECK_OK(__real_mbedtls_ssl_tls13_handshake_client_step(ssl)); - CHECK_OK(manage_resource(ssl, false)); + CHECK_OK(manage_resource(ssl, false, prev_state)); return 0; } int __wrap_mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) { - CHECK_OK(manage_resource(ssl, true)); + int prev_state = ssl->MBEDTLS_PRIVATE(state); + CHECK_OK(manage_resource(ssl, true, prev_state)); CHECK_OK(__real_mbedtls_ssl_write_client_hello(ssl)); - CHECK_OK(manage_resource(ssl, false)); + CHECK_OK(manage_resource(ssl, false, prev_state)); return 0; } diff --git a/components/mbedtls/port/dynamic/esp_ssl_srv.c b/components/mbedtls/port/dynamic/esp_ssl_srv.c index d200009226..9c50894fa7 100644 --- a/components/mbedtls/port/dynamic/esp_ssl_srv.c +++ b/components/mbedtls/port/dynamic/esp_ssl_srv.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,9 +29,9 @@ static bool ssl_ciphersuite_uses_rsa_key_ex(mbedtls_ssl_context *ssl) } #endif -static int manage_resource(mbedtls_ssl_context *ssl, bool add) +static int manage_resource(mbedtls_ssl_context *ssl, bool add, int prev_state) { - int state = add ? ssl->MBEDTLS_PRIVATE(state) : ssl->MBEDTLS_PRIVATE(state) - 1; + int state = add ? ssl->MBEDTLS_PRIVATE(state) : prev_state; if (mbedtls_ssl_is_handshake_over(ssl) || ssl->MBEDTLS_PRIVATE(handshake) == NULL) { return 0; @@ -207,11 +207,12 @@ static int manage_resource(mbedtls_ssl_context *ssl, bool add) int __wrap_mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) { - CHECK_OK(manage_resource(ssl, true)); + int prev_state = ssl->MBEDTLS_PRIVATE(state); + CHECK_OK(manage_resource(ssl, true, prev_state)); CHECK_OK(__real_mbedtls_ssl_handshake_server_step(ssl)); - CHECK_OK(manage_resource(ssl, false)); + CHECK_OK(manage_resource(ssl, false, prev_state)); return 0; } diff --git a/components/mbedtls/port/dynamic/esp_ssl_tls.c b/components/mbedtls/port/dynamic/esp_ssl_tls.c index 7036e66913..942d0dc02f 100644 --- a/components/mbedtls/port/dynamic/esp_ssl_tls.c +++ b/components/mbedtls/port/dynamic/esp_ssl_tls.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -379,15 +379,9 @@ int __wrap_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t * and prepare for the next read. So we have to update the msglen * by ourselves and free the rx buffer if no more data is available. */ - if (ssl->MBEDTLS_PRIVATE(in_hslen) < ssl->MBEDTLS_PRIVATE(in_msglen)) { + if (ssl->MBEDTLS_PRIVATE(in_hslen) == ssl->MBEDTLS_PRIVATE(in_msglen)) { ssl->MBEDTLS_PRIVATE(in_msglen) -= ssl->MBEDTLS_PRIVATE(in_hslen); - memmove(ssl->MBEDTLS_PRIVATE(in_msg), ssl->MBEDTLS_PRIVATE(in_msg) + ssl->MBEDTLS_PRIVATE(in_hslen), - ssl->MBEDTLS_PRIVATE(in_msglen)); - MBEDTLS_PUT_UINT16_BE(ssl->MBEDTLS_PRIVATE(in_msglen), ssl->in_len, 0); - } else { - ssl->MBEDTLS_PRIVATE(in_msglen) = 0; } - ssl->MBEDTLS_PRIVATE(in_hslen) = 0; } } #endif // CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 diff --git a/examples/protocols/esp_http_client/main/esp_http_client_example.c b/examples/protocols/esp_http_client/main/esp_http_client_example.c index 3ea4f32e31..3ddfdb2ba5 100644 --- a/examples/protocols/esp_http_client/main/esp_http_client_example.c +++ b/examples/protocols/esp_http_client/main/esp_http_client_example.c @@ -431,6 +431,7 @@ static void https_with_url(void) .url = "https://www.howsmyssl.com", .event_handler = _http_event_handler, .crt_bundle_attach = esp_crt_bundle_attach, + .timeout_ms = 5000, }; ESP_LOGI(TAG, "HTTPS request with url =>"); esp_http_client_handle_t client = esp_http_client_init(&config); @@ -477,6 +478,7 @@ static void https_with_hostname_path(void) .transport_type = HTTP_TRANSPORT_OVER_SSL, .event_handler = _http_event_handler, .cert_pem = howsmyssl_com_root_cert_pem_start, + .timeout_ms = 5000, }; ESP_LOGI(TAG, "HTTPS request with hostname and path =>"); esp_http_client_handle_t client = esp_http_client_init(&config);