mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 05:34:32 +02:00
feat(mbedtls): Add configuration to control dynamic buffer strategy in mbedtls
Problem: 1. In low-memory scenarios, the dynamic buffer feature can fail due to memory fragmentation. 2. It requires a contiguous 16KB heap chunk, but continuous allocation and deallocation of the RX buffer can lead to fragmentation. 3. If another component allocates memory between these operations, it can break up the available 16KB block, causing allocation failure. Solution: 1. Introduce configurable strategy for using dynamic buffers in TLS connections. 2. For example, convert RX buffers to static after the TLS handshake. 3. Allow users to select the strategy via a new field in the esp_http_client_cfg_t structure. 4. The strategy can be controlled independently for each TLS session.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -91,6 +91,12 @@ typedef enum {
|
|||||||
ESP_TLS_VER_TLS_MAX, /* to indicate max */
|
ESP_TLS_VER_TLS_MAX, /* to indicate max */
|
||||||
} esp_tls_proto_ver_t;
|
} esp_tls_proto_ver_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_TLS_DYN_BUF_RX_STATIC = 1, /*!< Strategy to disable dynamic RX buffer allocations and convert to static allocation post-handshake, reducing memory fragmentation */
|
||||||
|
ESP_TLS_DYN_BUF_STRATEGY_MAX, /*!< to indicate max */
|
||||||
|
} esp_tls_dyn_buf_strategy_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ESP-TLS configuration parameters
|
* @brief ESP-TLS configuration parameters
|
||||||
*
|
*
|
||||||
@@ -211,6 +217,11 @@ typedef struct esp_tls_cfg {
|
|||||||
const int *ciphersuites_list; /*!< Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites.
|
const int *ciphersuites_list; /*!< Pointer to a zero-terminated array of IANA identifiers of TLS ciphersuites.
|
||||||
Please check the list validity by esp_tls_get_ciphersuites_list() API */
|
Please check the list validity by esp_tls_get_ciphersuites_list() API */
|
||||||
esp_tls_proto_ver_t tls_version; /*!< TLS protocol version of the connection, e.g., TLS 1.2, TLS 1.3 (default - no preference) */
|
esp_tls_proto_ver_t tls_version; /*!< TLS protocol version of the connection, e.g., TLS 1.2, TLS 1.3 (default - no preference) */
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
esp_tls_dyn_buf_strategy_t esp_tls_dyn_buf_strategy; /*!< ESP-TLS dynamic buffer strategy */
|
||||||
|
#endif
|
||||||
|
|
||||||
} esp_tls_cfg_t;
|
} esp_tls_cfg_t;
|
||||||
|
|
||||||
#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS)
|
#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS)
|
||||||
@@ -464,7 +475,7 @@ int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_t
|
|||||||
* - >=0 if write operation was successful, the return value is the number
|
* - >=0 if write operation was successful, the return value is the number
|
||||||
* of bytes actually written to the TLS/SSL connection.
|
* of bytes actually written to the TLS/SSL connection.
|
||||||
* - <0 if write operation was not successful, because either an
|
* - <0 if write operation was not successful, because either an
|
||||||
* error occured or an action must be taken by the calling process.
|
* error occurred or an action must be taken by the calling process.
|
||||||
* - ESP_TLS_ERR_SSL_WANT_READ/
|
* - ESP_TLS_ERR_SSL_WANT_READ/
|
||||||
* ESP_TLS_ERR_SSL_WANT_WRITE.
|
* ESP_TLS_ERR_SSL_WANT_WRITE.
|
||||||
* if the handshake is incomplete and waiting for data to be available for reading.
|
* if the handshake is incomplete and waiting for data to be available for reading.
|
||||||
@@ -485,7 +496,7 @@ ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_t datalen);
|
|||||||
* - 0 if read operation was not successful. The underlying
|
* - 0 if read operation was not successful. The underlying
|
||||||
* connection was closed.
|
* connection was closed.
|
||||||
* - <0 if read operation was not successful, because either an
|
* - <0 if read operation was not successful, because either an
|
||||||
* error occured or an action must be taken by the calling process.
|
* error occurred or an action must be taken by the calling process.
|
||||||
*/
|
*/
|
||||||
ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen);
|
ssize_t esp_tls_conn_read(esp_tls_t *tls, void *data, size_t datalen);
|
||||||
|
|
||||||
@@ -537,7 +548,7 @@ esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *sockfd);
|
|||||||
*
|
*
|
||||||
* @param[in] sockfd sockfd value to set.
|
* @param[in] sockfd sockfd value to set.
|
||||||
*
|
*
|
||||||
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated withthe provided value
|
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated with the provided value
|
||||||
* - ESP_ERR_INVALID_ARG if (tls == NULL || sockfd < 0)
|
* - ESP_ERR_INVALID_ARG if (tls == NULL || sockfd < 0)
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_tls_set_conn_sockfd(esp_tls_t *tls, int sockfd);
|
esp_err_t esp_tls_set_conn_sockfd(esp_tls_t *tls, int sockfd);
|
||||||
@@ -549,7 +560,7 @@ esp_err_t esp_tls_set_conn_sockfd(esp_tls_t *tls, int sockfd);
|
|||||||
*
|
*
|
||||||
* @param[out] conn_state pointer to the connection state value.
|
* @param[out] conn_state pointer to the connection state value.
|
||||||
*
|
*
|
||||||
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated withthe provided value
|
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated with the provided value
|
||||||
* - ESP_ERR_INVALID_ARG (Invalid arguments)
|
* - ESP_ERR_INVALID_ARG (Invalid arguments)
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_tls_get_conn_state(esp_tls_t *tls, esp_tls_conn_state_t *conn_state);
|
esp_err_t esp_tls_get_conn_state(esp_tls_t *tls, esp_tls_conn_state_t *conn_state);
|
||||||
@@ -561,7 +572,7 @@ esp_err_t esp_tls_get_conn_state(esp_tls_t *tls, esp_tls_conn_state_t *conn_stat
|
|||||||
*
|
*
|
||||||
* @param[in] conn_state connection state value to set.
|
* @param[in] conn_state connection state value to set.
|
||||||
*
|
*
|
||||||
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated withthe provided value
|
* @return - ESP_OK on success and value of sockfd for the tls connection shall updated with the provided value
|
||||||
* - ESP_ERR_INVALID_ARG (Invalid arguments)
|
* - ESP_ERR_INVALID_ARG (Invalid arguments)
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_tls_set_conn_state(esp_tls_t *tls, esp_tls_conn_state_t conn_state);
|
esp_err_t esp_tls_set_conn_state(esp_tls_t *tls, esp_tls_conn_state_t conn_state);
|
||||||
@@ -586,7 +597,7 @@ void *esp_tls_get_ssl_context(esp_tls_t *tls);
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK if creating global CA store was successful.
|
* - ESP_OK if creating global CA store was successful.
|
||||||
* - ESP_ERR_NO_MEM if an error occured when allocating the mbedTLS resources.
|
* - ESP_ERR_NO_MEM if an error occurred when allocating the mbedTLS resources.
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_tls_init_global_ca_store(void);
|
esp_err_t esp_tls_init_global_ca_store(void);
|
||||||
|
|
||||||
@@ -605,7 +616,7 @@ esp_err_t esp_tls_init_global_ca_store(void);
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK if adding certificates was successful.
|
* - ESP_OK if adding certificates was successful.
|
||||||
* - Other if an error occured or an action must be taken by the calling process.
|
* - Other if an error occurred or an action must be taken by the calling process.
|
||||||
*/
|
*/
|
||||||
esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes);
|
esp_err_t esp_tls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes);
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
#include "mbedtls/esp_mbedtls_dynamic.h"
|
||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
#include "ecdsa/ecdsa_alt.h"
|
#include "ecdsa/ecdsa_alt.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -104,6 +104,10 @@ esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const
|
|||||||
|
|
||||||
mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
|
mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
tls->esp_tls_dyn_buf_strategy = ((esp_tls_cfg_t *)cfg)->esp_tls_dyn_buf_strategy;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (tls->role == ESP_TLS_CLIENT) {
|
if (tls->role == ESP_TLS_CLIENT) {
|
||||||
esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls);
|
esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls);
|
||||||
if (esp_ret != ESP_OK) {
|
if (esp_ret != ESP_OK) {
|
||||||
@@ -219,6 +223,15 @@ int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
|
|||||||
#endif
|
#endif
|
||||||
ret = mbedtls_ssl_handshake(&tls->ssl);
|
ret = mbedtls_ssl_handshake(&tls->ssl);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
if (tls->esp_tls_dyn_buf_strategy != 0) {
|
||||||
|
ret = esp_mbedtls_dynamic_set_rx_buf_static(&tls->ssl);
|
||||||
|
if (ret != 0) {
|
||||||
|
ESP_LOGE(TAG, "esp_mbedtls_dynamic_set_rx_buf_static returned -0x%04X", -ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
tls->conn_state = ESP_TLS_DONE;
|
tls->conn_state = ESP_TLS_DONE;
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
|
||||||
|
@@ -94,6 +94,10 @@ struct esp_tls {
|
|||||||
|
|
||||||
esp_tls_error_handle_t error_handle; /*!< handle to error descriptor */
|
esp_tls_error_handle_t error_handle; /*!< handle to error descriptor */
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
esp_tls_dyn_buf_strategy_t esp_tls_dyn_buf_strategy; /*!< ESP-TLS dynamic buffer strategy */
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function pointer for the server configuration API
|
// Function pointer for the server configuration API
|
||||||
|
@@ -34,6 +34,8 @@ static const char *TAG = "HTTP_CLIENT";
|
|||||||
|
|
||||||
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_ANY == (int)ESP_TLS_VER_ANY, "Enum mismatch in esp_http_client and esp-tls");
|
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_ANY == (int)ESP_TLS_VER_ANY, "Enum mismatch in esp_http_client and esp-tls");
|
||||||
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_MAX <= (int)ESP_TLS_VER_TLS_MAX, "HTTP client supported TLS is not supported in esp-tls");
|
ESP_STATIC_ASSERT((int)ESP_HTTP_CLIENT_TLS_VER_MAX <= (int)ESP_TLS_VER_TLS_MAX, "HTTP client supported TLS is not supported in esp-tls");
|
||||||
|
ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_RX_STATIC == (int)ESP_TLS_DYN_BUF_RX_STATIC, "Enum mismatch in esp_http_client and esp-tls");
|
||||||
|
ESP_STATIC_ASSERT((int)HTTP_TLS_DYN_BUF_STRATEGY_MAX <= (int)ESP_TLS_DYN_BUF_STRATEGY_MAX, "HTTP client supported TLS is not supported in esp-tls");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP Buffer
|
* HTTP Buffer
|
||||||
@@ -767,6 +769,14 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
|
|||||||
}
|
}
|
||||||
esp_transport_ssl_set_tls_version(ssl, config->tls_version);
|
esp_transport_ssl_set_tls_version(ssl, config->tls_version);
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
/* When tls_dyn_buf_strategy is 0, mbedTLS dynamic buffer allocation uses default behavior.
|
||||||
|
* No need to call esp_transport_ssl_set_esp_tls_dyn_buf_strategy() in this case */
|
||||||
|
if (config->tls_dyn_buf_strategy != 0 && config->tls_dyn_buf_strategy < HTTP_TLS_DYN_BUF_STRATEGY_MAX) {
|
||||||
|
esp_transport_ssl_set_esp_tls_dyn_buf_strategy(ssl, config->tls_dyn_buf_strategy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT
|
#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT
|
||||||
if (config->use_secure_element) {
|
if (config->use_secure_element) {
|
||||||
esp_transport_ssl_use_secure_element(ssl);
|
esp_transport_ssl_use_secure_element(ssl);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -137,6 +137,11 @@ typedef enum {
|
|||||||
HTTP_ADDR_TYPE_INET6 = AF_INET6, /**< IPv6 address family. */
|
HTTP_ADDR_TYPE_INET6 = AF_INET6, /**< IPv6 address family. */
|
||||||
} esp_http_client_addr_type_t;
|
} esp_http_client_addr_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTP_TLS_DYN_BUF_RX_STATIC = 1, /*!< Strategy to disable dynamic RX buffer allocations and convert to static allocation post-handshake, reducing memory fragmentation */
|
||||||
|
HTTP_TLS_DYN_BUF_STRATEGY_MAX, /*!< to indicate max */
|
||||||
|
} esp_http_client_tls_dyn_buf_strategy_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HTTP configuration
|
* @brief HTTP configuration
|
||||||
*/
|
*/
|
||||||
@@ -199,6 +204,10 @@ typedef struct {
|
|||||||
struct esp_transport_item_t *transport;
|
struct esp_transport_item_t *transport;
|
||||||
#endif
|
#endif
|
||||||
esp_http_client_addr_type_t addr_type; /*!< Address type used in http client configurations */
|
esp_http_client_addr_type_t addr_type; /*!< Address type used in http client configurations */
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
esp_http_client_tls_dyn_buf_strategy_t tls_dyn_buf_strategy; /*!< TLS dynamic buffer strategy */
|
||||||
|
#endif
|
||||||
} esp_http_client_config_t;
|
} esp_http_client_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -18,6 +18,17 @@
|
|||||||
|
|
||||||
#define TX_IDLE_BUFFER_SIZE (MBEDTLS_SSL_HEADER_LEN + CACHE_BUFFER_SIZE)
|
#define TX_IDLE_BUFFER_SIZE (MBEDTLS_SSL_HEADER_LEN + CACHE_BUFFER_SIZE)
|
||||||
|
|
||||||
|
#define ESP_MBEDTLS_RETURN_IF_RX_BUF_STATIC(ssl) \
|
||||||
|
do { \
|
||||||
|
if (ssl->MBEDTLS_PRIVATE(in_buf)) { \
|
||||||
|
esp_mbedtls_ssl_buf_states state = esp_mbedtls_get_buf_state(ssl->MBEDTLS_PRIVATE(in_buf)); \
|
||||||
|
if (state == ESP_MBEDTLS_SSL_BUF_STATIC) { \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
static const char *TAG = "Dynamic Impl";
|
static const char *TAG = "Dynamic Impl";
|
||||||
|
|
||||||
static void esp_mbedtls_set_buf_state(unsigned char *buf, esp_mbedtls_ssl_buf_states state)
|
static void esp_mbedtls_set_buf_state(unsigned char *buf, esp_mbedtls_ssl_buf_states state)
|
||||||
@@ -140,6 +151,29 @@ static void init_rx_buffer(mbedtls_ssl_context *ssl, unsigned char *buf)
|
|||||||
ssl->MBEDTLS_PRIVATE(in_left) = 0;
|
ssl->MBEDTLS_PRIVATE(in_left) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_mbedtls_dynamic_set_rx_buf_static(mbedtls_ssl_context *ssl)
|
||||||
|
{
|
||||||
|
unsigned char cache_buf[16];
|
||||||
|
memcpy(cache_buf, ssl->MBEDTLS_PRIVATE(in_buf), 16);
|
||||||
|
esp_mbedtls_reset_free_rx_buffer(ssl);
|
||||||
|
|
||||||
|
struct esp_mbedtls_ssl_buf *esp_buf;
|
||||||
|
int buffer_len = tx_buffer_len(ssl, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||||
|
esp_buf = mbedtls_calloc(1, SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
|
||||||
|
if (!esp_buf) {
|
||||||
|
ESP_LOGE(TAG, "rx buf alloc(%d bytes) failed", SSL_BUF_HEAD_OFFSET_SIZE + buffer_len);
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
esp_mbedtls_init_ssl_buf(esp_buf, buffer_len);
|
||||||
|
init_rx_buffer(ssl, esp_buf->buf);
|
||||||
|
|
||||||
|
memcpy(ssl->MBEDTLS_PRIVATE(in_ctr), cache_buf, 8);
|
||||||
|
memcpy(ssl->MBEDTLS_PRIVATE(in_iv), cache_buf + 8, 8);
|
||||||
|
esp_mbedtls_set_buf_state(ssl->MBEDTLS_PRIVATE(in_buf), ESP_MBEDTLS_SSL_BUF_STATIC);
|
||||||
|
return ESP_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context *ssl, int len)
|
static int esp_mbedtls_alloc_tx_buf(mbedtls_ssl_context *ssl, int len)
|
||||||
{
|
{
|
||||||
struct esp_mbedtls_ssl_buf *esp_buf;
|
struct esp_mbedtls_ssl_buf *esp_buf;
|
||||||
@@ -324,6 +358,12 @@ exit:
|
|||||||
|
|
||||||
int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl)
|
int esp_mbedtls_add_rx_buffer(mbedtls_ssl_context *ssl)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If RX buffer is set to static mode, this macro will return early
|
||||||
|
* and skip dynamic buffer allocation logic below
|
||||||
|
*/
|
||||||
|
ESP_MBEDTLS_RETURN_IF_RX_BUF_STATIC(ssl);
|
||||||
|
|
||||||
int cached = 0;
|
int cached = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int buffer_len;
|
int buffer_len;
|
||||||
@@ -403,6 +443,12 @@ exit:
|
|||||||
|
|
||||||
int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl)
|
int esp_mbedtls_free_rx_buffer(mbedtls_ssl_context *ssl)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* If RX buffer is set to static mode, this macro will return early
|
||||||
|
* and skip dynamic buffer free logic below
|
||||||
|
*/
|
||||||
|
ESP_MBEDTLS_RETURN_IF_RX_BUF_STATIC(ssl);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned char buf[16];
|
unsigned char buf[16];
|
||||||
struct esp_mbedtls_ssl_buf *esp_buf;
|
struct esp_mbedtls_ssl_buf *esp_buf;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#include "mbedtls/esp_mbedtls_dynamic.h"
|
||||||
|
|
||||||
#define TRACE_CHECK(_fn, _state) \
|
#define TRACE_CHECK(_fn, _state) \
|
||||||
({ \
|
({ \
|
||||||
ESP_LOGV(TAG, "%d " _state " to do \"%s\"", __LINE__, # _fn); \
|
ESP_LOGV(TAG, "%d " _state " to do \"%s\"", __LINE__, # _fn); \
|
||||||
@@ -48,8 +50,9 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ESP_MBEDTLS_SSL_BUF_CACHED,
|
ESP_MBEDTLS_SSL_BUF_CACHED = 0,
|
||||||
ESP_MBEDTLS_SSL_BUF_NO_CACHED,
|
ESP_MBEDTLS_SSL_BUF_NO_CACHED,
|
||||||
|
ESP_MBEDTLS_SSL_BUF_STATIC,
|
||||||
} esp_mbedtls_ssl_buf_states;
|
} esp_mbedtls_ssl_buf_states;
|
||||||
|
|
||||||
struct esp_mbedtls_ssl_buf {
|
struct esp_mbedtls_ssl_buf {
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mbedtls/ssl.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the dynamic buffer rx statically after the handshake. This is to avoid frequent allocation and deallocation of dynamic buffer.
|
||||||
|
*
|
||||||
|
* @param ssl mbedtls ssl context
|
||||||
|
* @return esp_err_t
|
||||||
|
* - ESP_OK: Successfully set the rx buffer to static
|
||||||
|
* - ESP_ERR_NO_MEM: Failed to allocate memory for the rx buffer
|
||||||
|
*/
|
||||||
|
esp_err_t esp_mbedtls_dynamic_set_rx_buf_static(mbedtls_ssl_context *ssl);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +61,15 @@ void esp_transport_ssl_crt_bundle_attach(esp_transport_handle_t t, esp_err_t ((*
|
|||||||
*/
|
*/
|
||||||
void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t);
|
void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t);
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
/**
|
||||||
|
* @brief Set ESP-TLS dynamic buffer strategy for ESP-TLS connection
|
||||||
|
*
|
||||||
|
* @param t ssl transport
|
||||||
|
* @param[in] strategy ESP-TLS dynamic buffer strategy
|
||||||
|
*/
|
||||||
|
void esp_transport_ssl_set_esp_tls_dyn_buf_strategy(esp_transport_handle_t t, esp_tls_dyn_buf_strategy_t strategy);
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Set TLS protocol version for ESP-TLS connection
|
* @brief Set TLS protocol version for ESP-TLS connection
|
||||||
*
|
*
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -350,6 +350,14 @@ void esp_transport_ssl_enable_global_ca_store(esp_transport_handle_t t)
|
|||||||
ssl->cfg.use_global_ca_store = true;
|
ssl->cfg.use_global_ca_store = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
void esp_transport_ssl_set_esp_tls_dyn_buf_strategy(esp_transport_handle_t t, esp_tls_dyn_buf_strategy_t strategy)
|
||||||
|
{
|
||||||
|
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||||
|
ssl->cfg.esp_tls_dyn_buf_strategy = strategy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void esp_transport_ssl_set_tls_version(esp_transport_handle_t t, esp_tls_proto_ver_t tls_version)
|
void esp_transport_ssl_set_tls_version(esp_transport_handle_t t, esp_tls_proto_ver_t tls_version)
|
||||||
{
|
{
|
||||||
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
|
||||||
|
@@ -51,4 +51,13 @@ menu "Example Configuration"
|
|||||||
help
|
help
|
||||||
Select ethernet interface to pass the OTA data.
|
Select ethernet interface to pass the OTA data.
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config EXAMPLE_TLS_DYN_BUF_RX_STATIC
|
||||||
|
bool "Use static rx buffer for dynamic buffer after TLS handshake"
|
||||||
|
depends on MBEDTLS_DYNAMIC_BUFFER
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This converts the dynamic RX buffer to static allocation after the TLS handshake
|
||||||
|
is complete. This reduces memory fragmentation by avoiding repeated dynamic
|
||||||
|
allocations during data transfer.
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -101,6 +101,12 @@ void simple_ota_example_task(void *pvParameter)
|
|||||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||||
.if_name = &ifr,
|
.if_name = &ifr,
|
||||||
#endif
|
#endif
|
||||||
|
#if CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC
|
||||||
|
/* This part applies static buffer strategy for rx dynamic buffer.
|
||||||
|
* This is to avoid frequent allocation and deallocation of dynamic buffer.
|
||||||
|
*/
|
||||||
|
.tls_dyn_buf_strategy = HTTP_TLS_DYN_BUF_RX_STATIC,
|
||||||
|
#endif /* CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
|
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
import http.server
|
import http.server
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
@@ -6,6 +6,7 @@ import os
|
|||||||
import ssl
|
import ssl
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Any
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ import pexpect
|
|||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
|
from common_test_methods import get_env_config_variable, get_host_ip4_by_dest_ip
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@@ -130,6 +132,20 @@ def calc_all_sha256(dut: Dut) -> Tuple[str, str]:
|
|||||||
return str(sha256_bootloader), str(sha256_app)
|
return str(sha256_bootloader), str(sha256_app)
|
||||||
|
|
||||||
|
|
||||||
|
def setting_connection(dut: Dut, env_name: Optional[str] = None) -> Any:
|
||||||
|
if env_name is not None and dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True:
|
||||||
|
dut.expect('Please input ssid password:')
|
||||||
|
ap_ssid = get_env_config_variable(env_name, 'ap_ssid')
|
||||||
|
ap_password = get_env_config_variable(env_name, 'ap_password')
|
||||||
|
dut.write(f'{ap_ssid} {ap_password}')
|
||||||
|
try:
|
||||||
|
ip_address = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode()
|
||||||
|
print(f'Connected to AP/Ethernet with IP: {ip_address}')
|
||||||
|
except pexpect.exceptions.TIMEOUT:
|
||||||
|
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP/Ethernet')
|
||||||
|
return get_host_ip4_by_dest_ip(ip_address)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.esp32
|
@pytest.mark.esp32
|
||||||
@pytest.mark.esp32c3
|
@pytest.mark.esp32c3
|
||||||
@pytest.mark.esp32s3
|
@pytest.mark.esp32s3
|
||||||
@@ -387,6 +403,39 @@ def test_examples_protocol_simple_ota_example_tls1_3(dut: Dut) -> None:
|
|||||||
tls1_3_server.kill()
|
tls1_3_server.kill()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.esp32
|
||||||
|
@pytest.mark.ethernet_ota
|
||||||
|
@pytest.mark.parametrize('config', ['tls1_2_dynamic',], indirect=True)
|
||||||
|
def test_examples_protocol_simple_ota_example_tls1_2_dynamic(dut: Dut) -> None:
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. join AP/Ethernet
|
||||||
|
2. Fetch OTA image over HTTPS
|
||||||
|
3. Reboot with the new OTA image
|
||||||
|
"""
|
||||||
|
sha256_bootloader, sha256_app = calc_all_sha256(dut)
|
||||||
|
# Start server
|
||||||
|
thread1 = multiprocessing.Process(target=start_https_server, args=(dut.app.binary_path, '0.0.0.0', 8001))
|
||||||
|
thread1.daemon = True
|
||||||
|
thread1.start()
|
||||||
|
try:
|
||||||
|
# start test
|
||||||
|
dut.expect(f'Loaded app from partition at offset 0x10000', timeout=30)
|
||||||
|
check_sha256(sha256_bootloader, str(dut.expect(r'SHA-256 for bootloader:\s+([a-f0-9]){64}')[0]))
|
||||||
|
check_sha256(sha256_app, str(dut.expect(r'SHA-256 for current firmware:\s+([a-f0-9]){64}')[0]))
|
||||||
|
|
||||||
|
host_ip = setting_connection(dut)
|
||||||
|
|
||||||
|
dut.expect('Starting OTA example task', timeout=30)
|
||||||
|
dut.write(f'https://{host_ip}:8001/simple_ota.bin')
|
||||||
|
dut.expect('OTA Succeed, Rebooting...', timeout=120)
|
||||||
|
# after reboot
|
||||||
|
dut.expect(f'Loaded app from partition at offset 0x110000', timeout=30)
|
||||||
|
dut.expect('OTA example app_main start', timeout=10)
|
||||||
|
finally:
|
||||||
|
thread1.terminate()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if sys.argv[2:]: # if two or more arguments provided:
|
if sys.argv[2:]: # if two or more arguments provided:
|
||||||
# Usage: pytest_simple_ota.py <image_dir> <server_port> [cert_di>]
|
# Usage: pytest_simple_ota.py <image_dir> <server_port> [cert_di>]
|
||||||
|
@@ -0,0 +1,15 @@
|
|||||||
|
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
|
||||||
|
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_CONNECT_WIFI=n
|
||||||
|
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_IP101=y
|
||||||
|
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
|
||||||
|
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
||||||
|
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||||
|
CONFIG_EXAMPLE_TLS_DYN_BUF_RX_STATIC=y
|
Reference in New Issue
Block a user