From 2325a727d8399167ec7eb46913b352b9a82344ac Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 8 Apr 2026 18:37:10 +0530 Subject: [PATCH 01/12] feat(esp-tls): Add unified private key interface via esp_key_config_t Add ESP_KEY_SOURCE_BUFFER and ESP_KEY_SOURCE_PSA key sources so all hardware backends (DS, ECDSA, secure element) are accessed via PSA key IDs through a single esp_tls_cfg_t.client_key field. (cherry picked from commit 36090b7161177636f5c9cab3f8ed9c36ac2011cb) --- components/esp-tls/CMakeLists.txt | 10 +- components/esp-tls/Kconfig | 10 - components/esp-tls/esp_tls.h | 11 +- components/esp-tls/esp_tls_mbedtls.c | 203 +++++++----------- components/esp_http_client/CMakeLists.txt | 4 +- components/esp_http_client/esp_http_client.c | 40 ++-- .../esp_http_client/include/esp_http_client.h | 5 +- .../include/esp_https_server.h | 9 +- .../esp_https_server/src/https_server.c | 61 +++--- components/esp_security/CMakeLists.txt | 4 +- .../esp_security/include/esp_key_config.h | 69 ++++++ .../tcp_transport/include/esp_transport_ssl.h | 31 ++- components/tcp_transport/transport_ssl.c | 14 +- .../main/esp_local_ctrl_service.c | 11 +- .../protocols/https_server/simple/main/main.c | 11 +- .../wss_server/main/wss_server_example.c | 11 +- tools/mocks/esp-tls/CMakeLists.txt | 2 +- 17 files changed, 270 insertions(+), 236 deletions(-) create mode 100644 components/esp_security/include/esp_key_config.h diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt index 14a8503cd5c..44207ecab90 100644 --- a/components/esp-tls/CMakeLists.txt +++ b/components/esp-tls/CMakeLists.txt @@ -22,7 +22,10 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto PRIV_INCLUDE_DIRS "private_include" - REQUIRES mbedtls + # mbedtls is public requirements because esp_tls.h + # includes mbedtls header files. + # esp_security is public because esp_tls.h includes esp_key_config.h + REQUIRES mbedtls esp_security PRIV_REQUIRES ${priv_req}) @@ -34,8 +37,3 @@ else() target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_TLS_WITH_LWIP=1) endif() endif() - - -if(CONFIG_ESP_TLS_USE_SECURE_ELEMENT) - idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib) -endif() diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index ef9904e3a4e..185c158e6c8 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -22,16 +22,6 @@ menu "ESP-TLS" esp_tls_stack_ops_t interface. endchoice - config ESP_TLS_USE_SECURE_ELEMENT - bool "Use Secure Element (ATECC608A) with ESP-TLS" - depends on ESP_TLS_USING_MBEDTLS - select ATCA_MBEDTLS_ECDSA - select ATCA_MBEDTLS_ECDSA_SIGN - select ATCA_MBEDTLS_ECDSA_VERIFY - help - Enable use of Secure Element for ESP-TLS, this enables internal support for - ATECC608A peripheral, which can be used for TLS connection. - config ESP_TLS_USE_DS_PERIPHERAL bool "Use Digital Signature (DS) Peripheral with ESP-TLS" depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index c7802b94185..3d7596959ec 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -9,6 +9,7 @@ #include #include "esp_err.h" #include "esp_tls_errors.h" +#include "esp_key_config.h" #include "sdkconfig.h" #ifdef CONFIG_ESP_TLS_USING_MBEDTLS #include "mbedtls/ssl.h" @@ -160,6 +161,8 @@ typedef struct esp_tls_cfg { const unsigned char *clientkey_pem_buf; /*!< Client key legacy name */ }; + const esp_key_config_t *client_key; /*!< Unified key config. Must remain valid for session lifetime */ + union { unsigned int clientkey_bytes; /*!< Size of client key pointed to by clientkey_pem_buf @@ -184,9 +187,6 @@ typedef struct esp_tls_cfg { underneath socket will be configured in non blocking mode after tls session is established */ - bool use_secure_element; /*!< Enable this option to use secure element or - atecc608a chip */ - int timeout_ms; /*!< Network 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 @@ -315,6 +315,8 @@ typedef struct esp_tls_cfg_server { const unsigned char *serverkey_pem_buf; /*!< Server key legacy name */ }; + const esp_key_config_t *server_key; /*!< Unified key config. Must remain valid for session lifetime */ + union { unsigned int serverkey_bytes; /*!< Size of server key pointed to by serverkey_pem_buf */ @@ -334,9 +336,6 @@ typedef struct esp_tls_cfg_server { esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */ - 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 diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 901d4ba713b..5c0050091b8 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -32,16 +32,6 @@ #include "esp_crt_bundle.h" #endif -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT -/* cryptoauthlib includes */ -#include "mbedtls/atca_mbedtls_wrap.h" -#include "tng_atca.h" -#include "cryptoauthlib.h" -static const atcacert_def_t *cert_def = NULL; -/* Prototypes for functions */ -static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, const void *pki); -#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */ - #if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) #include #include "psa/crypto.h" @@ -486,6 +476,7 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) if (!tls) { return; } + if (tls->cacert_ptr != global_cacert) { mbedtls_x509_crt_free(tls->cacert_ptr); } @@ -511,9 +502,6 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) mbedtls_pk_free(&tls->clientkey); mbedtls_ssl_config_free(&tls->conf); mbedtls_ssl_free(&tls->ssl); -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT - atcab_release(); -#endif } static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len) @@ -757,28 +745,51 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) #endif // CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL } - if (cfg->use_secure_element) { -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT + if (cfg->server_key != NULL && cfg->server_key->source == ESP_KEY_SOURCE_BUFFER) { + /* Unified key config with buffer source */ esp_tls_pki_t pki = { .public_cert = &tls->servercert, .pk_key = &tls->serverkey, .publiccert_pem_buf = cfg->servercert_buf, .publiccert_pem_bytes = cfg->servercert_bytes, - .privkey_pem_buf = NULL, - .privkey_pem_bytes = 0, - .privkey_password = NULL, - .privkey_password_len = 0, + .privkey_pem_buf = cfg->server_key->buffer.data, + .privkey_pem_bytes = cfg->server_key->buffer.len, + .privkey_password = (const unsigned char *)cfg->server_key->buffer.password, + .privkey_password_len = cfg->server_key->buffer.password_len, }; - - ret = esp_set_atecc608a_pki_context(tls, (void*) &pki); - if (ret != ESP_OK) { - return ret; + esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set server pki context"); + return esp_ret; } -#else - ESP_LOGE(TAG, "Please enable secure element support for ESP-TLS in menuconfig"); - return ESP_FAIL; -#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */ - } else if (cfg->use_ecdsa_peripheral) { + } else if (cfg->server_key != NULL && cfg->server_key->source == ESP_KEY_SOURCE_PSA) { + mbedtls_svc_key_id_t key_id = cfg->server_key->psa.key_id; + mbedtls_pk_init(&tls->serverkey); + ret = mbedtls_pk_wrap_psa(&tls->serverkey, key_id); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; + } + if (cfg->servercert_buf != NULL) { + mbedtls_x509_crt_init(&tls->servercert); + ret = mbedtls_x509_crt_parse(&tls->servercert, cfg->servercert_buf, cfg->servercert_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->servercert, &tls->serverkey); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; + } + } + } else if (cfg->use_ecdsa_peripheral) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; #if SOC_ECDSA_SUPPORT_CURVE_P384 @@ -997,26 +1008,50 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #endif } - if (cfg->use_secure_element) { -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT + if (cfg->client_key != NULL && cfg->client_key->source == ESP_KEY_SOURCE_BUFFER) { + /* Unified key config with buffer source */ esp_tls_pki_t pki = { .public_cert = &tls->clientcert, .pk_key = &tls->clientkey, .publiccert_pem_buf = cfg->clientcert_buf, .publiccert_pem_bytes = cfg->clientcert_bytes, - .privkey_pem_buf = NULL, - .privkey_pem_bytes = 0, - .privkey_password = NULL, - .privkey_password_len = 0, + .privkey_pem_buf = cfg->client_key->buffer.data, + .privkey_pem_bytes = cfg->client_key->buffer.len, + .privkey_password = (const unsigned char *)cfg->client_key->buffer.password, + .privkey_password_len = cfg->client_key->buffer.password_len, }; - ret = esp_set_atecc608a_pki_context(tls, (void*) &pki); - if (ret != ESP_OK) { - return ret; + esp_err_t esp_ret = set_pki_context(tls, &pki); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set client pki context"); + return esp_ret; + } + } else if (cfg->client_key != NULL && cfg->client_key->source == ESP_KEY_SOURCE_PSA) { + mbedtls_svc_key_id_t key_id = cfg->client_key->psa.key_id; + mbedtls_pk_init(&tls->clientkey); + ret = mbedtls_pk_wrap_psa(&tls->clientkey, key_id); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; + } + if (cfg->clientcert_buf != NULL) { + mbedtls_x509_crt_init(&tls->clientcert); + ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_buf, cfg->clientcert_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; + } } -#else - ESP_LOGE(TAG, "Please enable secure element support for ESP-TLS in menuconfig"); - return ESP_FAIL; -#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */ } else if (cfg->ds_data != NULL) { #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL if (cfg->clientcert_pem_buf == NULL) { @@ -1278,92 +1313,6 @@ const int *esp_mbedtls_get_ciphersuites_list(void) return mbedtls_ssl_list_ciphersuites(); } -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT -static esp_err_t esp_init_atecc608a(uint8_t i2c_addr) -{ - cfg_ateccx08a_i2c_default.atcai2c.address = i2c_addr; - int ret = atcab_init(&cfg_ateccx08a_i2c_default); - if(ret != 0) { - ESP_LOGE(TAG, "Failed to initialize atca device, returned -0x%04X", -ret); - return ESP_FAIL; - } - return ESP_OK; -} - -static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, const void *pki) -{ - int ret = 0; - esp_err_t esp_ret = ESP_FAIL; - ESP_LOGI(TAG, "Initialize the ATECC interface..."); - (void)esp_ret; - (void)cert_def; -#if defined(CONFIG_ATECC608A_TNG) || defined(CONFIG_ATECC608A_TFLEX) -#ifdef CONFIG_ATECC608A_TNG - esp_ret = esp_init_atecc608a(CONFIG_ATCA_I2C_ADDRESS); - if (ret != ESP_OK) { - return ESP_ERR_ESP_TLS_SE_FAILED; - } -#elif CONFIG_ATECC608A_TFLEX /* CONFIG_ATECC608A_TNG */ - esp_ret = esp_init_atecc608a(CONFIG_ATCA_I2C_ADDRESS); - if (ret != ESP_OK) { - return ESP_ERR_ESP_TLS_SE_FAILED; - } -#endif /* CONFIG_ATECC608A_TFLEX */ - mbedtls_x509_crt_init(&tls->clientcert); - ret = tng_get_device_cert_def(&cert_def); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to get device cert def"); - return ESP_ERR_ESP_TLS_SE_FAILED; - } - - /* Extract the device certificate and convert to mbedtls cert */ - ret = atca_mbedtls_cert_add(&tls->clientcert, cert_def); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to parse cert from device, return 0x%04X", ret); - mbedtls_print_error_msg(ret); - return ESP_ERR_ESP_TLS_SE_FAILED; - } -#elif CONFIG_ATECC608A_TCUSTOM - esp_ret = esp_init_atecc608a(CONFIG_ATCA_I2C_ADDRESS); - if (ret != ESP_OK) { - return ESP_ERR_ESP_TLS_SE_FAILED; - } - mbedtls_x509_crt_init(&tls->clientcert); - - esp_tls_pki_t *pki_l = (esp_tls_pki_t *) pki; - if (pki_l->publiccert_pem_buf != NULL) { - ret = mbedtls_x509_crt_parse(&tls->clientcert, pki_l->publiccert_pem_buf, pki_l->publiccert_pem_bytes); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse of client cert returned -0x%04X", -ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; - } - } else { - ESP_LOGE(TAG, "Device certificate must be provided for TrustCustom Certs"); - return ESP_FAIL; - } -#endif /* CONFIG_ATECC608A_TCUSTOM */ - ret = atca_mbedtls_pk_init(&tls->clientkey, 0); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to parse key from device"); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - mbedtls_print_error_msg(ret); - return ESP_ERR_ESP_TLS_SE_FAILED; - } - - ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to configure client cert, returned -0x%04X", ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_ESP_TLS_SE_FAILED; - } - - return ESP_OK; -} -#endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */ - #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL /* * tf-psa-crypto 1.1 made mbedtls_pk_wrap_psa() call psa_export_public_key() on diff --git a/components/esp_http_client/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt index 4a353e33ca0..b52b45bb847 100644 --- a/components/esp_http_client/CMakeLists.txt +++ b/components/esp_http_client/CMakeLists.txt @@ -1,7 +1,7 @@ if(NOT ${IDF_TARGET} STREQUAL "linux") - set(req lwip esp_event) + set(req lwip esp_event esp_security) else() - set(req linux esp_event) + set(req linux esp_event esp_security) endif() idf_component_register(SRCS "esp_http_client.c" diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 1567cd21cdb..52dfd0f2544 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -938,12 +938,6 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co } #endif -#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT - if (config->use_secure_element) { - esp_transport_ssl_use_secure_element(ssl); - } -#endif - #if CONFIG_ESP_TLS_USE_DS_PERIPHERAL if (config->ds_data != NULL) { esp_transport_ssl_set_ds_data(ssl, config->ds_data); @@ -962,26 +956,32 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co } #endif - if (config->client_key_pem) { - if (!config->client_key_len) { - esp_transport_ssl_set_client_key_data(ssl, config->client_key_pem, strlen(config->client_key_pem)); - } else { - esp_transport_ssl_set_client_key_data_der(ssl, config->client_key_pem, config->client_key_len); + /* Check for unified key config */ + if (config->client_key != NULL) { + esp_transport_ssl_set_client_key_config(ssl, config->client_key); + } else { + /* Legacy key configuration */ + if (config->client_key_pem) { + if (!config->client_key_len) { + esp_transport_ssl_set_client_key_data(ssl, config->client_key_pem, strlen(config->client_key_pem)); + } else { + esp_transport_ssl_set_client_key_data_der(ssl, config->client_key_pem, config->client_key_len); + } } - } #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (config->use_ecdsa_peripheral) { + if (config->use_ecdsa_peripheral) { #if SOC_ECDSA_SUPPORT_CURVE_P384 - esp_transport_ssl_set_client_key_ecdsa_peripheral_extended(ssl, config->ecdsa_key_efuse_blk, config->ecdsa_key_efuse_blk_high); + esp_transport_ssl_set_client_key_ecdsa_peripheral_extended(ssl, config->ecdsa_key_efuse_blk, config->ecdsa_key_efuse_blk_high); #else - esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk); + esp_transport_ssl_set_client_key_ecdsa_peripheral(ssl, config->ecdsa_key_efuse_blk); #endif - // Set the ECDSA curve - esp_transport_ssl_set_ecdsa_curve(ssl, config->ecdsa_curve); - } + // Set the ECDSA curve + esp_transport_ssl_set_ecdsa_curve(ssl, config->ecdsa_curve); + } #endif - if (config->client_key_password && config->client_key_password_len > 0) { - esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len); + if (config->client_key_password && config->client_key_password_len > 0) { + esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len); + } } if (config->skip_cert_common_name_check) { diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 4a257808778..1a6225b76be 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -10,6 +10,7 @@ #include "freertos/FreeRTOS.h" #include "sdkconfig.h" #include "esp_err.h" +#include "esp_key_config.h" #include #ifdef __cplusplus @@ -200,6 +201,7 @@ typedef struct { DER Certificate - Length of the buffer pointed to by client_cert_der. Should be the length of the certificate. */ const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */ size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */ + const esp_key_config_t *client_key; /*!< Unified client key configuration. Takes precedence over client_key_pem when set */ const char *client_key_password; /*!< Client key decryption password string */ size_t client_key_password_len; /*!< String length of the password pointed to by client_key_password */ esp_http_client_proto_ver_t tls_version; /*!< TLS protocol version of the connection, e.g., TLS 1.2, TLS 1.3 (default - no preference) */ @@ -237,9 +239,6 @@ typedef struct { const char **alpn_protos; /*!< Application protocols required for HTTP2. If HTTP2/ALPN support is required, a list of protocols that should be negotiated. The format is length followed by protocol name. For the most common cases the following is ok: const char **alpn_protos = { "h2", NULL }; - where 'h2' is the protocol name */ #endif -#if CONFIG_ESP_TLS_USE_SECURE_ELEMENT - bool use_secure_element; /*!< Enable this option to use secure element */ -#endif #if CONFIG_ESP_TLS_USE_DS_PERIPHERAL void *ds_data; /*!< Pointer for digital signature peripheral context, see ESP-TLS Documentation for more details */ #endif diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 2a34eb7ebad..58d568e21ea 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -105,6 +105,9 @@ struct httpd_ssl_config { /** Private key byte length */ size_t prvtkey_len; + /** Unified key config. Takes precedence over prvtkey_pem when set */ + const esp_key_config_t *server_key; + /** Use ECDSA peripheral to use private key */ bool use_ecdsa_peripheral; @@ -129,9 +132,6 @@ struct httpd_ssl_config { /** Enable tls session tickets */ bool session_tickets; - /** Enable secure element for server session */ - bool use_secure_element; - /** User callback for esp_https_server */ esp_https_server_user_cb *user_cb; @@ -227,7 +227,6 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; .port_secure = 443, \ .port_insecure = 80, \ .session_tickets = false, \ - .use_secure_element = false, \ .user_cb = NULL, \ .ssl_userdata = NULL, \ .cert_select_cb = NULL, \ diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index 865560777d8..2184228087a 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -348,48 +348,47 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht #endif } - /* Pass on secure element boolean */ - cfg->use_secure_element = config->use_secure_element; - if (!cfg->use_secure_element) { - if (config->use_ecdsa_peripheral) { + if (config->use_ecdsa_peripheral) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; - (*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk; + (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; + (*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk = config->ecdsa_key_efuse_blk; #if SOC_ECDSA_SUPPORT_CURVE_P384 - (*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk_high = config->ecdsa_key_efuse_blk_high; + (*ssl_ctx)->tls_cfg->ecdsa_key_efuse_blk_high = config->ecdsa_key_efuse_blk_high; #endif - (*ssl_ctx)->tls_cfg->ecdsa_curve = config->ecdsa_curve; + (*ssl_ctx)->tls_cfg->ecdsa_curve = config->ecdsa_curve; #else - ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig."); - ret = ESP_ERR_NOT_SUPPORTED; - goto exit; + ESP_LOGE(TAG, "Please enable the support for signing using ECDSA peripheral in menuconfig."); + ret = ESP_ERR_NOT_SUPPORTED; + goto exit; #endif - } else if (config->prvtkey_pem != NULL && config->prvtkey_len > 0) { - cfg->serverkey_buf = malloc(config->prvtkey_len); + } else if (config->server_key != NULL) { + /* Unified key config - pass directly to esp_tls */ + cfg->server_key = config->server_key; + } else if (config->prvtkey_pem != NULL && config->prvtkey_len > 0) { + cfg->serverkey_buf = malloc(config->prvtkey_len); - if (cfg->serverkey_buf) { - memcpy((char *) cfg->serverkey_buf, config->prvtkey_pem, config->prvtkey_len); - cfg->serverkey_bytes = config->prvtkey_len; - } else { - ESP_LOGE(TAG, "Could not allocate memory for server key"); - ret = ESP_ERR_NO_MEM; - goto exit; - } + if (cfg->serverkey_buf) { + memcpy((char *) cfg->serverkey_buf, config->prvtkey_pem, config->prvtkey_len); + cfg->serverkey_bytes = config->prvtkey_len; } else { + ESP_LOGE(TAG, "Could not allocate memory for server key"); + ret = ESP_ERR_NO_MEM; + goto exit; + } + } else { #if defined(CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK) - if (config->cert_select_cb == NULL) { - ESP_LOGE(TAG, "No Server key supplied and no certificate selection hook is present"); - ret = ESP_ERR_INVALID_ARG; - goto exit; - } else { - ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the certificate selection hook"); - } -#else - ESP_LOGE(TAG, "No Server key supplied"); + if (config->cert_select_cb == NULL) { + ESP_LOGE(TAG, "No Server key supplied and no certificate selection hook is present"); ret = ESP_ERR_INVALID_ARG; goto exit; -#endif + } else { + ESP_LOGW(TAG, "Server key not supplied, make sure to supply it in the certificate selection hook"); } +#else + ESP_LOGE(TAG, "No Server key supplied"); + ret = ESP_ERR_INVALID_ARG; + goto exit; +#endif } return ret; diff --git a/components/esp_security/CMakeLists.txt b/components/esp_security/CMakeLists.txt index c3568afce4e..530e72325f1 100644 --- a/components/esp_security/CMakeLists.txt +++ b/components/esp_security/CMakeLists.txt @@ -2,7 +2,9 @@ idf_build_get_property(target IDF_TARGET) idf_build_get_property(non_os_build NON_OS_BUILD) if(${target} STREQUAL "linux") - return() # This component is not supported by the POSIX/Linux simulator + # On linux, only provide headers (esp_key_config.h) without any source files + idf_component_register(INCLUDE_DIRS "include") + return() endif() set(srcs "") diff --git a/components/esp_security/include/esp_key_config.h b/components/esp_security/include/esp_key_config.h new file mode 100644 index 00000000000..35da2f4babb --- /dev/null +++ b/components/esp_security/include/esp_key_config.h @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Key format */ +typedef enum { + ESP_KEY_FORMAT_AUTO = 0, /*!< Auto-detect */ + ESP_KEY_FORMAT_PEM, /*!< PEM (base64) */ + ESP_KEY_FORMAT_DER, /*!< DER (binary) */ + ESP_KEY_FORMAT_RAW, /*!< Raw key bytes */ +} esp_key_format_t; + +/** + * Key source types + * + * Hardware-backed key sources (DS peripheral, ECDSA peripheral, + * secure element, key manager) as well as software PSA imported keys + * are accessed via PSA Crypto drivers. Use ESP_KEY_SOURCE_PSA with + * the PSA key ID obtained from psa_import_key() or the corresponding + * hardware setup helper API. + */ +typedef enum { + ESP_KEY_SOURCE_NONE = 0, /*!< No private key configured */ + ESP_KEY_SOURCE_BUFFER, /*!< Key in memory buffer (PEM/DER/RAW) */ + ESP_KEY_SOURCE_PSA, /*!< PSA Crypto key (opaque or transparent) */ +} esp_key_source_t; + +/** + * Unified private key configuration + * + * For hardware-backed keys (DS peripheral, ECDSA peripheral, ATECC608, + * key manager), use ESP_KEY_SOURCE_PSA with the key ID returned by + * the respective setup helper (e.g., esp_secure_element_psa_setup()). + * + * @note Must remain valid for the entire TLS session lifetime + */ +typedef struct esp_key_config { + esp_key_source_t source; /*!< Key source type */ + + union { + struct { + const void *data; /*!< Key data (PEM/DER/RAW) */ + size_t len; /*!< Length (0 for null-terminated PEM) */ + const char *password; /*!< Decryption password */ + size_t password_len; /*!< Password length */ + esp_key_format_t format; /*!< Key format */ + } buffer; + + struct { + uint32_t key_id; /*!< PSA key identifier */ + } psa; + }; + +} esp_key_config_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 4dcd5c1338a..b0ec044a305 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -206,15 +206,6 @@ void esp_transport_ssl_set_common_name(esp_transport_handle_t t, const char *com */ void esp_transport_ssl_set_ciphersuites_list(esp_transport_handle_t t, const int *ciphersuites_list); -/** - * @brief Set the ssl context to use secure element (atecc608a) for client(device) private key and certificate - * - * @note Recommended to be used with ESP32 series interfaced to ATECC608A based secure element - * - * @param t ssl transport - */ -void esp_transport_ssl_use_secure_element(esp_transport_handle_t t); - /** * @brief Set the ds_data handle in ssl context.(used for the digital signature operation) * @@ -223,6 +214,26 @@ void esp_transport_ssl_use_secure_element(esp_transport_handle_t t); */ void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data); +/** + * @brief Set unified client key configuration for mutual authentication + * + * This function provides a unified way to configure client private keys + * from various sources (buffer, ECDSA peripheral, secure element, etc.) + * using the esp_key_config_t structure. + * + * @note This function stores the pointer to config, rather than making a copy. + * So the config must remain valid until after the connection is cleaned up. + * + * @note When client_key is set, it takes precedence over legacy key configuration + * functions (set_client_key_data, set_client_key_ecdsa_peripheral, etc.) + * + * @param t ssl transport + * @param[in] client_key Pointer to the unified key configuration + * + * @see esp_key_config_t for configuration options + */ +void esp_transport_ssl_set_client_key_config(esp_transport_handle_t t, const esp_key_config_t *client_key); + /** * @brief Set PSK key and hint for PSK server/client verification in esp-tls component. * Important notes: diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 790ebd37c10..0f01ebecb87 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -502,14 +502,6 @@ void esp_transport_ssl_set_ciphersuites_list(esp_transport_handle_t t, const int ssl->cfg.ciphersuites_list = ciphersuites_list; } -#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT -void esp_transport_ssl_use_secure_element(esp_transport_handle_t t) -{ - GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t); - ssl->cfg.use_secure_element = true; -} -#endif - #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE void esp_transport_ssl_crt_bundle_attach(esp_transport_handle_t t, esp_err_t ((*crt_bundle_attach)(void *conf))) { @@ -575,6 +567,12 @@ void esp_transport_ssl_set_ds_data(esp_transport_handle_t t, void *ds_data) } #endif +void esp_transport_ssl_set_client_key_config(esp_transport_handle_t t, const esp_key_config_t *client_key) +{ + GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t); + ssl->cfg.client_key = client_key; +} + void esp_transport_ssl_set_keep_alive(esp_transport_handle_t t, esp_transport_keep_alive_t *keep_alive_cfg) { GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t); diff --git a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c index f0ff5b9d274..084e80a1249 100644 --- a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c +++ b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c @@ -20,6 +20,7 @@ #include #include #include +#include #include static const char *TAG = "control"; @@ -239,8 +240,14 @@ void start_esp_local_ctrl_service(void) /* Load server private key */ extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); - https_conf.prvtkey_pem = prvtkey_pem_start; - https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; + static esp_key_config_t server_key = { + .source = ESP_KEY_SOURCE_BUFFER, + .buffer = { + .data = prvtkey_pem_start, + .len = prvtkey_pem_end - prvtkey_pem_start, + } + }; + https_conf.server_key = &server_key; #else httpd_config_t http_conf = HTTPD_DEFAULT_CONFIG(); #endif diff --git a/examples/protocols/https_server/simple/main/main.c b/examples/protocols/https_server/simple/main/main.c index 30878614d17..deb33c722e1 100644 --- a/examples/protocols/https_server/simple/main/main.c +++ b/examples/protocols/https_server/simple/main/main.c @@ -25,6 +25,7 @@ #include #include "esp_tls.h" +#include "esp_key_config.h" #include "sdkconfig.h" #if CONFIG_EXAMPLE_ENABLE_HTTPS_SERVER_CUSTOM_CIPHERSUITES @@ -206,8 +207,14 @@ static httpd_handle_t start_webserver(void) extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); - conf.prvtkey_pem = prvtkey_pem_start; - conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; + static esp_key_config_t server_key = { + .source = ESP_KEY_SOURCE_BUFFER, + .buffer = { + .data = prvtkey_pem_start, + .len = prvtkey_pem_end - prvtkey_pem_start, + } + }; + conf.server_key = &server_key; #if CONFIG_EXAMPLE_ENABLE_HTTPS_SERVER_CUSTOM_CIPHERSUITES static const int ciphersuites_to_use[] = { diff --git a/examples/protocols/https_server/wss_server/main/wss_server_example.c b/examples/protocols/https_server/wss_server/main/wss_server_example.c index 7588c839749..b3c529f06f1 100644 --- a/examples/protocols/https_server/wss_server/main/wss_server_example.c +++ b/examples/protocols/https_server/wss_server/main/wss_server_example.c @@ -22,6 +22,7 @@ #include #endif // !CONFIG_IDF_TARGET_LINUX #include +#include "esp_key_config.h" #include "keep_alive.h" #include "sdkconfig.h" @@ -211,8 +212,14 @@ static httpd_handle_t start_wss_echo_server(void) extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); - conf.prvtkey_pem = prvtkey_pem_start; - conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; + static esp_key_config_t server_key = { + .source = ESP_KEY_SOURCE_BUFFER, + .buffer = { + .data = prvtkey_pem_start, + .len = prvtkey_pem_end - prvtkey_pem_start, + } + }; + conf.server_key = &server_key; esp_err_t ret = httpd_ssl_start(&server, &conf); if (ESP_OK != ret) { diff --git a/tools/mocks/esp-tls/CMakeLists.txt b/tools/mocks/esp-tls/CMakeLists.txt index 8e0406e2958..450513b9f00 100644 --- a/tools/mocks/esp-tls/CMakeLists.txt +++ b/tools/mocks/esp-tls/CMakeLists.txt @@ -8,6 +8,6 @@ idf_component_mock(INCLUDE_DIRS "${original_esp_tls_dir}" "${original_esp_tls_dir}/esp-tls-crypto" MOCK_HEADER_FILES ${original_esp_tls_dir}/esp_tls.h ${original_esp_tls_dir}/esp-tls-crypto/esp_tls_crypto.h - REQUIRES mbedtls + REQUIRES mbedtls esp_security ) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-array-parameter) From a35e0568160192228bd82351375cccd7be9d246b Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 8 Apr 2026 18:39:34 +0530 Subject: [PATCH 02/12] feat(mbedtls): Add PSA Crypto driver for external secure elements Add generic secure element PSA driver with runtime callback registration. Consolidate Kconfig into single MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED option. Closes https://github.com/espressif/esp-idf/issues/18388 (cherry picked from commit 1c20f525b404eaa84742da922530aa523c499ebb) --- components/mbedtls/CMakeLists.txt | 13 +- components/mbedtls/Kconfig | 31 +- .../config/mbedtls_preset_default.conf | 3 +- .../mbedtls/port/include/mbedtls/esp_config.h | 9 +- .../psa_crypto_driver_secure_element.h | 239 +++++++++ ...sa_crypto_driver_secure_element_contexts.h | 65 +++ .../psa_crypto_driver_secure_element.c | 487 ++++++++++++++++++ components/mbedtls/sdkconfig.rename | 5 + docs/en/api-reference/protocols/esp_tls.rst | 45 +- .../zh_CN/api-reference/protocols/esp_tls.rst | 39 +- 10 files changed, 889 insertions(+), 47 deletions(-) create mode 100644 components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h create mode 100644 components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h create mode 100644 components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c create mode 100644 components/mbedtls/sdkconfig.rename diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 0bfd1f4ebf9..7eb0369b468 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -477,6 +477,14 @@ if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mbedtls_rom_osi_functions_init") endif() +if(CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c") + target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include") + target_compile_definitions(tfpsacrypto PRIVATE + SECURE_ELEMENT_DRIVER_ENABLED) +endif() + if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-analyzer") target_compile_options(tfpsacrypto PRIVATE "-fno-analyzer") @@ -544,11 +552,6 @@ if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM) target_link_libraries(tfpsacrypto PRIVATE idf::esp_timer) endif() -# # Link esp-cryptoauthlib to mbedtls -# if(CONFIG_ATCA_MBEDTLS_ECDSA) -# mbedcrypto_optional_deps(espressif__esp-cryptoauthlib esp-cryptoauthlib) -# endif() - # Apply -fno-analyzer to ALL mbedTLS targets at the very end when all targets are created if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") message(STATUS "Applying -fno-analyzer to all mbedTLS targets...") diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index ea5f41dc2b5..79ea78a0358 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -1000,49 +1000,49 @@ menu "mbedTLS" config MBEDTLS_ECP_DP_SECP384R1_ENABLED bool "Enable SECP384R1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help Enable support for SECP384R1 Elliptic Curve. config MBEDTLS_ECP_DP_SECP521R1_ENABLED bool "Enable SECP521R1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help Enable support for SECP521R1 Elliptic Curve. config MBEDTLS_ECP_DP_SECP256K1_ENABLED bool "Enable SECP256K1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help Enable support for SECP256K1 Elliptic Curve. config MBEDTLS_ECP_DP_BP256R1_ENABLED bool "Enable BP256R1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help support for DP Elliptic Curve. config MBEDTLS_ECP_DP_BP384R1_ENABLED bool "Enable BP384R1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help support for DP Elliptic Curve. config MBEDTLS_ECP_DP_BP512R1_ENABLED bool "Enable BP512R1 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help support for DP Elliptic Curve. config MBEDTLS_ECP_DP_CURVE25519_ENABLED bool "Enable CURVE25519 curve" depends on MBEDTLS_ECP_C - default y if !(MBEDTLS_ATCA_HW_ECDSA_SIGN || MBEDTLS_ATCA_HW_ECDSA_VERIFY) + default y help Enable support for CURVE25519 Elliptic Curve. endmenu @@ -1510,19 +1510,14 @@ menu "mbedTLS" it also increases the binary size by ~1.2 KB as it pulls in the peripheral's block mode code as well. - config MBEDTLS_ATCA_HW_ECDSA_SIGN - bool "Enable hardware ECDSA sign acceleration when using ATECC608A" + config MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED + bool "Enable secure element hardware support (e.g., ATECC608A)" default n help - This option enables hardware acceleration for ECDSA sign function, only - when using ATECC608A cryptoauth chip. - - config MBEDTLS_ATCA_HW_ECDSA_VERIFY - bool "Enable hardware ECDSA verify acceleration when using ATECC608A" - default n - help - This option enables hardware acceleration for ECDSA sign function, only - when using ATECC608A cryptoauth chip. + Enable PSA Crypto driver support for external secure elements. + This enables sign, verify, and key export operations via runtime-registered + callbacks from the secure element component (e.g., esp-cryptoauthlib). + The private key never leaves the secure element. config MBEDTLS_HARDWARE_RSA_DS_PERIPHERAL bool "Enable hardware RSA digital signature peripheral acceleration" diff --git a/components/mbedtls/config/mbedtls_preset_default.conf b/components/mbedtls/config/mbedtls_preset_default.conf index 11047ec88fe..e9b78ce9469 100644 --- a/components/mbedtls/config/mbedtls_preset_default.conf +++ b/components/mbedtls/config/mbedtls_preset_default.conf @@ -153,8 +153,7 @@ CONFIG_MBEDTLS_HARDWARE_ECC=y CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK=y CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN=n CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY=y -CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN=n -CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY=n +CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED=n CONFIG_MBEDTLS_PKCS7_C=y CONFIG_MBEDTLS_PKCS1_V15=y diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index f877145a555..fd67f7bccb3 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -267,13 +267,8 @@ #endif #endif -#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN -#define MBEDTLS_ECDSA_SIGN_ALT -#endif - -#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY -#define MBEDTLS_ECDSA_VERIFY_ALT -#endif +/* SECURE_ELEMENT_DRIVER_ENABLED is set via target_compile_definitions in + * CMakeLists.txt when CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED is set. */ #ifdef CONFIG_MBEDTLS_HARDWARE_ECC #ifdef CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h new file mode 100644 index 00000000000..6a0831ba0ab --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "psa/crypto.h" +#include "psa/crypto_types.h" + +#include "psa_crypto_driver_secure_element_contexts.h" + +#if defined(SECURE_ELEMENT_DRIVER_ENABLED) || defined(CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED) +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Secure element PSA driver location + * + * Vendor-specific location for secure element keys. + * Bits 8-31 are location, using vendor flag (0x800000) + SE vendor ID. + */ +#define PSA_KEY_LOCATION_SECURE_ELEMENT ((psa_key_location_t) 0x800004) + +/** + * @brief Construct a lifetime for secure element keys with default persistence + */ +#define PSA_KEY_LIFETIME_SECURE_ELEMENT \ + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ + PSA_KEY_PERSISTENCE_DEFAULT, \ + PSA_KEY_LOCATION_SECURE_ELEMENT) + +/** + * @brief Construct a volatile lifetime for secure element keys + */ +#define PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE \ + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ + PSA_KEY_PERSISTENCE_VOLATILE, \ + PSA_KEY_LOCATION_SECURE_ELEMENT) + +/* + * Callback typedefs for secure element operations. + * + * These allow the SE-specific backend (e.g. esp-cryptoauthlib for ATECC608A) + * to register its implementation at runtime without any build-time dependency. + */ + +/** + * @brief Callback to sign a hash using the secure element + * + * @param slot_id Slot containing the private key + * @param hash Hash to sign + * @param hash_len Length of hash (e.g. 32 for SHA-256) + * @param sig Output buffer for raw signature (R || S) + * @param sig_size Size of sig buffer + * @param sig_len Actual signature length written + * @return psa_status_t + */ +typedef psa_status_t (*secure_element_sign_cb_t)(uint8_t slot_id, const uint8_t *hash, size_t hash_len, + uint8_t *sig, size_t sig_size, size_t *sig_len); + +/** + * @brief Callback to export the public key from a secure element slot + * + * @param slot_id Slot containing the key pair + * @param pubkey Output buffer for raw public key (X || Y) + * @param pubkey_size Size of pubkey buffer + * @param pubkey_len Actual public key length written + * @return psa_status_t + */ +typedef psa_status_t (*secure_element_export_pubkey_cb_t)(uint8_t slot_id, uint8_t *pubkey, + size_t pubkey_size, size_t *pubkey_len); + +/** + * @brief Callback to verify a hash signature using the secure element + * + * @param hash Hash that was signed + * @param hash_len Length of hash + * @param sig Raw signature (R || S) + * @param sig_len Length of signature + * @param pubkey Raw public key (X || Y) + * @param pubkey_len Length of public key + * @param is_verified Output: true if signature is valid + * @return psa_status_t + */ +typedef psa_status_t (*secure_element_verify_cb_t)(const uint8_t *hash, size_t hash_len, + const uint8_t *sig, size_t sig_len, const uint8_t *pubkey, size_t pubkey_len, bool *is_verified); + +/** + * @brief Secure element callback table + * + * The algorithm, key_type, and key_bits fields declare what the SE supports. + * The driver validates incoming requests against these and returns + * PSA_ERROR_NOT_SUPPORTED for anything that doesn't match, allowing the + * PSA framework to fall back to software. + */ +typedef struct { + secure_element_sign_cb_t sign; /**< Sign hash callback (NULL if not supported) */ + secure_element_export_pubkey_cb_t export_pubkey; /**< Export public key callback (NULL if not supported) */ + secure_element_verify_cb_t verify; /**< Verify hash callback (NULL if not supported) */ + psa_algorithm_t algorithm; /**< Supported algorithm, e.g. PSA_ALG_ECDSA(PSA_ALG_SHA_256) */ + psa_key_type_t key_type; /**< Supported key type, e.g. PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) */ + size_t key_bits; /**< Supported key size in bits, e.g. 256 */ +} secure_element_callbacks_t; + +/** + * @brief Register secure element callbacks + * + * Must be called once during application initialization, before any PSA + * operations targeting PSA_KEY_LOCATION_SECURE_ELEMENT. Uses atomic + * compare-and-swap so only the first call succeeds. + * + * @param callbacks Pointer to callback table (must remain valid for program lifetime) + * @return PSA_SUCCESS on success + * @return PSA_ERROR_BAD_STATE if callbacks were already registered + * @return PSA_ERROR_INVALID_ARGUMENT if callbacks is NULL + */ +psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t *callbacks); + +/** + * @brief Sign a hash using secure element opaque driver + */ +psa_status_t secure_element_opaque_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * @brief Import a secure element key reference (not actual key material) + */ +psa_status_t secure_element_opaque_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits); + +/** + * @brief Export the public key from a secure element opaque key + */ +psa_status_t secure_element_opaque_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * @brief Get the key buffer size for a secure element opaque key + */ +size_t secure_element_opaque_size_function( + psa_key_type_t key_type, + size_t key_bits); + +/** + * @brief Verify a hash using secure element transparent driver + */ +psa_status_t secure_element_transparent_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * @brief Start a hash verification operation + */ +psa_status_t secure_element_transparent_verify_hash_start( + secure_element_transparent_verify_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * @brief Complete a hash verification operation + */ +psa_status_t secure_element_transparent_verify_hash_complete( + secure_element_transparent_verify_hash_operation_t *operation); + +/** + * @brief Abort a hash verification operation + */ +psa_status_t secure_element_transparent_verify_hash_abort( + secure_element_transparent_verify_hash_operation_t *operation); + +/** + * @brief Start a hash signing operation using opaque driver + */ +psa_status_t secure_element_opaque_sign_hash_start( + secure_element_opaque_sign_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length); + +/** + * @brief Complete a hash signing operation using opaque driver + */ +psa_status_t secure_element_opaque_sign_hash_complete( + secure_element_opaque_sign_hash_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * @brief Abort a hash signing operation using opaque driver + */ +psa_status_t secure_element_opaque_sign_hash_abort( + secure_element_opaque_sign_hash_operation_t *operation); + +#ifdef __cplusplus +} +#endif + +#endif /* SECURE_ELEMENT_DRIVER_ENABLED || CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED */ diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h new file mode 100644 index 00000000000..351e513fa01 --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Maximum key component length in bytes. + * Supports up to P-384 (48 bytes). Increase to 66 for P-521 if needed. + */ +#define SECURE_ELEMENT_MAX_KEY_BYTES 48 + +/** + * @brief Opaque key structure for secure element import + * + * This struct is passed as the "key material" to psa_import_key(). + * It identifies which SE slot the key refers to. + */ +typedef struct { + uint8_t slot_id; /**< Slot index on the secure element */ +} secure_element_opaque_key_t; + +/** + * @brief Operation context for transparent verify_hash + * + * Used by the interruptible verify API to store intermediate state + * between start / complete / abort calls. + */ +typedef struct { + uint8_t sha[SECURE_ELEMENT_MAX_KEY_BYTES]; + uint8_t r[SECURE_ELEMENT_MAX_KEY_BYTES]; + uint8_t s[SECURE_ELEMENT_MAX_KEY_BYTES]; + uint8_t qx[SECURE_ELEMENT_MAX_KEY_BYTES]; + uint8_t qy[SECURE_ELEMENT_MAX_KEY_BYTES]; + size_t key_len; + size_t sha_len; +} secure_element_transparent_verify_hash_operation_t; + +/** + * @brief Operation context for opaque sign_hash + * + * Used by the interruptible sign API to store intermediate state + * between start / complete / abort calls. + */ +typedef struct { + uint8_t sha[SECURE_ELEMENT_MAX_KEY_BYTES]; + size_t key_len; + size_t sha_len; + secure_element_opaque_key_t *opaque_key; + unsigned int alg; +} secure_element_opaque_sign_hash_operation_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c b/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c new file mode 100644 index 00000000000..351dc6348bd --- /dev/null +++ b/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c @@ -0,0 +1,487 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Generic Secure Element PSA Crypto Driver + * + * This driver provides PSA Crypto API integration for external secure elements + * (e.g., ATECC608A). The SE-specific operations are dispatched through + * runtime-registered callbacks, removing any build-time dependency on a + * particular SE library. + * + * The callbacks struct declares which algorithm/key_type/key_bits the SE + * supports. The driver validates each request against these and returns + * PSA_ERROR_NOT_SUPPORTED for mismatches, letting PSA fall back to software. + */ + +#include +#include +#include "sdkconfig.h" + +#ifdef SECURE_ELEMENT_DRIVER_ENABLED + +#include "esp_log.h" +#include "psa_crypto_driver_secure_element.h" + +static const char *TAG = "psa_crypto_driver_secure_element"; + +#define UNCOMPRESSED_POINT_FORMAT 0x04 + +/* Runtime-registered SE callbacks (set once via secure_element_register_callbacks) */ +static const secure_element_callbacks_t *s_se_callbacks = NULL; + +psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t *callbacks) +{ + if (callbacks == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (callbacks->key_bits == 0) { + ESP_LOGE(TAG, "key_bits must be set in callbacks"); + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Atomic compare-and-swap: only the first registration succeeds */ + const secure_element_callbacks_t *expected = NULL; + if (!atomic_compare_exchange_strong((volatile _Atomic(const secure_element_callbacks_t *) *)&s_se_callbacks, + &expected, callbacks)) { + ESP_LOGE(TAG, "Secure element callbacks already registered"); + return PSA_ERROR_BAD_STATE; + } + + return PSA_SUCCESS; +} + +/** + * @brief Get the registered callbacks, or NULL if not yet registered + */ +static inline const secure_element_callbacks_t *se_get_callbacks(void) +{ + return s_se_callbacks; +} + +/** + * @brief Check if a request matches the registered SE capabilities + * + * Compares the algorithm and key type from the request against what the SE + * declared at registration time. Returns PSA_ERROR_NOT_SUPPORTED on mismatch. + */ +static psa_status_t validate_request(psa_algorithm_t alg, const psa_key_attributes_t *attributes) +{ + const secure_element_callbacks_t *cbs = se_get_callbacks(); + if (!cbs) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Check algorithm family matches (e.g., both are ECDSA) */ + psa_algorithm_t registered_alg = cbs->algorithm; + + /* Use PSA_ALG_SIGN_GET_HASH to compare base algorithm ignoring hash */ + if (PSA_ALG_IS_ECDSA(registered_alg)) { + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + /* If registered with a specific hash, check it matches */ + psa_algorithm_t reg_hash = PSA_ALG_SIGN_GET_HASH(registered_alg); + if (reg_hash != PSA_ALG_ANY_HASH && reg_hash != PSA_ALG_SIGN_GET_HASH(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(registered_alg)) { + if (!PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + } else if (registered_alg != alg) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Check key type matches */ + if (attributes) { + psa_key_type_t req_type = psa_get_key_type(attributes); + /* Accept both key pair and public key for the same family */ + psa_key_type_t reg_base = PSA_KEY_TYPE_IS_KEY_PAIR(cbs->key_type) + ? PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(cbs->key_type)) + : cbs->key_type; + psa_key_type_t req_base = PSA_KEY_TYPE_IS_KEY_PAIR(req_type) + ? PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(req_type)) + : req_type; + if (reg_base != req_base) { + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Check key size matches */ + size_t req_bits = psa_get_key_bits(attributes); + if (req_bits != 0 && req_bits != cbs->key_bits) { + return PSA_ERROR_NOT_SUPPORTED; + } + } + + return PSA_SUCCESS; +} + +/* Transparent verify operations */ +psa_status_t secure_element_transparent_verify_hash_start( + secure_element_transparent_verify_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + if (!operation || !attributes || !key_buffer || !hash || !signature) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Validate against registered SE capabilities */ + psa_status_t status = validate_request(alg, attributes); + if (status != PSA_SUCCESS) { + return status; + } + + size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); + if (key_len == 0 || key_len > SECURE_ELEMENT_MAX_KEY_BYTES) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Verify key buffer can hold the uncompressed public key (0x04 || X || Y) */ + if (key_buffer_size < 1 + 2 * key_len) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Validate hash length matches key component length */ + if (hash_length != key_len) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (signature_length != 2 * key_len) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + /* Handle public key format - must be uncompressed (0x04 || X || Y) */ + if (key_buffer[0] != UNCOMPRESSED_POINT_FORMAT) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size != 2 * key_len + 1) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(secure_element_transparent_verify_hash_operation_t)); + operation->key_len = key_len; + operation->sha_len = hash_length; + + /* Big-endian format, matching PSA format */ + memcpy(operation->sha, hash, key_len); + memcpy(operation->r, signature, key_len); + memcpy(operation->s, signature + key_len, key_len); + + /* Extract public key coordinates (skip 0x04 format byte) */ + memcpy(operation->qx, key_buffer + 1, key_len); + memcpy(operation->qy, key_buffer + 1 + key_len, key_len); + + return PSA_SUCCESS; +} + +psa_status_t secure_element_transparent_verify_hash_complete(secure_element_transparent_verify_hash_operation_t *operation) +{ + if (!operation) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + const secure_element_callbacks_t *cbs = se_get_callbacks(); + if (!cbs || !cbs->verify) { + ESP_LOGE(TAG, "Secure element verify callback not registered"); + return PSA_ERROR_NOT_SUPPORTED; + } + + size_t key_len = operation->key_len; + + /* Construct public key (X || Y) */ + uint8_t pubkey[2 * SECURE_ELEMENT_MAX_KEY_BYTES]; + memcpy(pubkey, operation->qx, key_len); + memcpy(pubkey + key_len, operation->qy, key_len); + + /* Construct signature (R || S) */ + uint8_t sig[2 * SECURE_ELEMENT_MAX_KEY_BYTES]; + memcpy(sig, operation->r, key_len); + memcpy(sig + key_len, operation->s, key_len); + + /* Verify using registered SE callback */ + bool is_verified = false; + psa_status_t status = cbs->verify(operation->sha, operation->sha_len, + sig, 2 * key_len, + pubkey, 2 * key_len, + &is_verified); + + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "SE verify callback failed: 0x%04x", (unsigned)status); + return status; + } + + if (!is_verified) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + return PSA_SUCCESS; +} + +psa_status_t secure_element_transparent_verify_hash_abort(secure_element_transparent_verify_hash_operation_t *operation) +{ + if (operation) { + memset(operation, 0, sizeof(secure_element_transparent_verify_hash_operation_t)); + } + return PSA_SUCCESS; +} + +psa_status_t secure_element_transparent_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + secure_element_transparent_verify_hash_operation_t operation; + + psa_status_t status = secure_element_transparent_verify_hash_start( + &operation, attributes, key_buffer, key_buffer_size, + alg, hash, hash_length, signature, signature_length); + if (status != PSA_SUCCESS) { + return status; + } + + status = secure_element_transparent_verify_hash_complete(&operation); + if (status != PSA_SUCCESS) { + return status; + } + + return secure_element_transparent_verify_hash_abort(&operation); +} + +/* Opaque sign operations */ +psa_status_t secure_element_opaque_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits) +{ + if (!attributes || !data || data_length < 1 || !key_buffer || !key_buffer_length || !bits) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(secure_element_opaque_key_t) || data_length < sizeof(secure_element_opaque_key_t)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Validate the key attributes match what the SE supports */ + const secure_element_callbacks_t *cbs = se_get_callbacks(); + if (!cbs) { + return PSA_ERROR_NOT_SUPPORTED; + } + + psa_status_t status = validate_request(psa_get_key_algorithm(attributes), attributes); + if (status != PSA_SUCCESS) { + return status; + } + + memcpy(key_buffer, data, sizeof(secure_element_opaque_key_t)); + *key_buffer_length = sizeof(secure_element_opaque_key_t); + *bits = psa_get_key_bits(attributes); + return PSA_SUCCESS; +} + +psa_status_t secure_element_opaque_sign_hash_start( + secure_element_opaque_sign_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length) +{ + if (!operation || !attributes || !key_buffer || !hash) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(secure_element_opaque_key_t)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Validate against registered SE capabilities */ + psa_status_t status = validate_request(alg, attributes); + if (status != PSA_SUCCESS) { + return status; + } + + size_t component_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); + if (component_len == 0 || component_len > SECURE_ELEMENT_MAX_KEY_BYTES) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Validate hash length matches key component length */ + if (hash_length != component_len) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(secure_element_opaque_sign_hash_operation_t)); + operation->key_len = component_len; + memcpy(operation->sha, hash, component_len); + operation->opaque_key = (secure_element_opaque_key_t *) key_buffer; + operation->alg = alg; + operation->sha_len = hash_length; + + return PSA_SUCCESS; +} + +psa_status_t secure_element_opaque_sign_hash_complete( + secure_element_opaque_sign_hash_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length) +{ + if (!operation || !signature || !signature_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t component_len = operation->key_len; + + if (signature_size < 2 * component_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + const secure_element_callbacks_t *cbs = se_get_callbacks(); + if (!cbs || !cbs->sign) { + ESP_LOGE(TAG, "Secure element sign callback not registered"); + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Sign using registered SE callback */ + uint8_t sig[2 * SECURE_ELEMENT_MAX_KEY_BYTES]; + size_t sig_len = 0; + psa_status_t status = cbs->sign(operation->opaque_key->slot_id, + operation->sha, operation->sha_len, + sig, sizeof(sig), &sig_len); + + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "SE sign callback failed: 0x%04x", (unsigned)status); + return status; + } + + /* Copy signature to output (R || S format, big-endian - matches PSA) */ + memcpy(signature, sig, 2 * component_len); + *signature_length = 2 * component_len; + + return PSA_SUCCESS; +} + +psa_status_t secure_element_opaque_sign_hash_abort(secure_element_opaque_sign_hash_operation_t *operation) +{ + if (operation) { + memset(operation, 0, sizeof(secure_element_opaque_sign_hash_operation_t)); + } + return PSA_SUCCESS; +} + +psa_status_t secure_element_opaque_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + secure_element_opaque_sign_hash_operation_t operation; + + psa_status_t status = secure_element_opaque_sign_hash_start( + &operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length); + if (status != PSA_SUCCESS) { + secure_element_opaque_sign_hash_abort(&operation); + return status; + } + + status = secure_element_opaque_sign_hash_complete(&operation, signature, signature_size, signature_length); + if (status != PSA_SUCCESS) { + secure_element_opaque_sign_hash_abort(&operation); + return status; + } + + return secure_element_opaque_sign_hash_abort(&operation); +} + +psa_status_t secure_element_opaque_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + if (!attributes || !key_buffer || !data || !data_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(secure_element_opaque_key_t)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + const secure_element_opaque_key_t *opaque_key = (const secure_element_opaque_key_t *) key_buffer; + + const secure_element_callbacks_t *cbs = se_get_callbacks(); + if (!cbs || !cbs->export_pubkey) { + ESP_LOGE(TAG, "Secure element export_pubkey callback not registered"); + return PSA_ERROR_NOT_SUPPORTED; + } + + /* Get key length from registered capabilities */ + size_t key_len = PSA_BITS_TO_BYTES(cbs->key_bits); + + /* Need 1 byte for format + key_len bytes for x + key_len bytes for y */ + size_t required_size = 1 + (2 * key_len); + if (data_size < required_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Export public key using registered SE callback */ + uint8_t pubkey[2 * SECURE_ELEMENT_MAX_KEY_BYTES]; + size_t pubkey_len = 0; + psa_status_t status = cbs->export_pubkey(opaque_key->slot_id, pubkey, sizeof(pubkey), &pubkey_len); + + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "SE export_pubkey callback failed: 0x%04x", (unsigned)status); + return status; + } + + /* Format: uncompressed point (0x04 followed by x and y coordinates) */ + data[0] = UNCOMPRESSED_POINT_FORMAT; + memcpy(data + 1, pubkey, key_len); /* X coordinate */ + memcpy(data + 1 + key_len, pubkey + key_len, key_len); /* Y coordinate */ + + *data_length = required_size; + + return PSA_SUCCESS; +} + +size_t secure_element_opaque_size_function( + psa_key_type_t key_type, + size_t key_bits) +{ + (void)key_type; + (void)key_bits; + + /* Opaque keys always use the same size structure */ + return sizeof(secure_element_opaque_key_t); +} + +#endif /* SECURE_ELEMENT_DRIVER_ENABLED */ diff --git a/components/mbedtls/sdkconfig.rename b/components/mbedtls/sdkconfig.rename new file mode 100644 index 00000000000..580d93bb06f --- /dev/null +++ b/components/mbedtls/sdkconfig.rename @@ -0,0 +1,5 @@ +# Renamed ATCA/SE ECDSA options to generic secure element (v6.0) +CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED +CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED +CONFIG_MBEDTLS_SE_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED +CONFIG_MBEDTLS_SE_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 8f5f5b13b7c..a4affa7f260 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -207,23 +207,23 @@ To use a custom TLS stack in your project, follow these steps: ATECC608A (Secure Element) with ESP-TLS -------------------------------------------------- -ESP-TLS provides support for using ATECC608A cryptoauth chip with ESP32 series of SoCs. The use of ATECC608A is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. ESP-TLS uses MbedTLS as its underlying TLS/SSL stack by default unless changed manually. +ESP-TLS provides support for using ATECC608A cryptoauth chip with ESP32 series of SoCs via the PSA Crypto opaque driver interface. The use of ATECC608A is supported only when ESP-TLS is used with MbedTLS as its underlying SSL/TLS stack. ESP-TLS uses MbedTLS as its underlying TLS/SSL stack by default unless changed manually. .. note:: ATECC608A chip interfaced to ESP32 series must be already configured. For details, please refer to `esp_cryptoauth_utility `_. -To enable the secure element support, and use it in your project for TLS connection, you have to follow the below steps: +To enable the secure element support, and use it in your project for TLS connection, follow the steps below: -1) Add `esp-cryptoauthlib `_ in your project, for details please refer `how to use esp-cryptoauthlib with ESP-IDF `_. +1) Add `esp-cryptoauthlib `_ as a dependency in your project. For details, please refer to `how to use esp-cryptoauthlib with ESP-IDF `_. -2) Enable the menuconfig option :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT`: +2) Enable the menuconfig option :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`: .. code-block:: none - menuconfig > Component config > ESP-TLS > Use Secure Element (ATECC608A) with ESP-TLS + menuconfig > Component config > mbedTLS > Enable secure element hardware support -3) Select type of ATECC608A chip with following option: +3) Select the type of ATECC608A chip: .. code-block:: none @@ -231,13 +231,40 @@ To enable the secure element support, and use it in your project for TLS connect To know more about different types of ATECC608A chips and how to obtain the type of ATECC608A connected to your ESP module, please visit `ATECC608A chip type `_. -4) Enable the use of ATECC608A in ESP-TLS by providing the following config option in :cpp:type:`esp_tls_cfg_t`: +4) Import the ATECC608A key and configure ESP-TLS to use it via :cpp:type:`esp_key_config_t`: .. code-block:: c + #include "psa/crypto.h" + #include "psa_crypto_driver_secure_element.h" + #include "psa_crypto_driver_secure_element_contexts.h" + #include "esp_key_config.h" + + /* Import ATECC608A key reference into PSA */ + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&key_attr, 256); + + secure_element_opaque_key_t opaque_key = { + .slot_id = 0, /* Private key slot on ATECC608A */ + }; + + psa_key_id_t psa_key_id; + psa_import_key(&key_attr, (const uint8_t *)&opaque_key, + sizeof(opaque_key), &psa_key_id); + + /* Configure ESP-TLS to use the PSA key */ + esp_key_config_t key_config = { + .source = ESP_KEY_SOURCE_PSA, + .psa.key_id = psa_key_id, + }; + esp_tls_cfg_t cfg = { - /* other configurations options */ - .use_secure_element = true, + /* other configuration options */ + .client_key = &key_config, }; .. only:: SOC_DIG_SIGN_SUPPORTED diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 5db5fe2be4f..5d66d8d7059 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -207,7 +207,7 @@ ESP-TLS 组件支持通过 :cpp:func:`esp_tls_register_stack` API 注册自定 ESP-TLS 中的 ATECC608A(安全元件) ----------------------------------------- -ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须将 MbedTLS 作为 ESP-TLS 的底层 SSL/TLS 协议栈。未经手动更改,ESP-TLS 默认以 MbedTLS 为其底层 TLS/SSL 协议栈。 +ESP-TLS 支持通过 PSA Crypto 不透明驱动接口在 ESP32 系列芯片上使用 ATECC608A 加密芯片。使用 ATECC608A 时必须将 MbedTLS 作为 ESP-TLS 的底层 SSL/TLS 协议栈。未经手动更改,ESP-TLS 默认以 MbedTLS 为其底层 TLS/SSL 协议栈。 .. note:: @@ -215,13 +215,13 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须 要启用安全元件支持,并将其应用于工程 TLS 连接,请遵循以下步骤: -1) 在工程中添加 `esp-cryptoauthlib `_,详情请参阅 `如何在 ESP-IDF 中使用 esp-cryptoauthlib `_。 +1) 在工程中添加 `esp-cryptoauthlib `_ 作为依赖,详情请参阅 `如何在 ESP-IDF 中使用 esp-cryptoauthlib `_。 -2) 启用 menuconfig 选项 :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT`: +2) 启用 menuconfig 选项 :ref:`CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED`: .. code-block:: none - menuconfig > Component config > ESP-TLS > Use Secure Element (ATECC608A) with ESP-TLS + menuconfig > Component config > mbedTLS > Enable secure element hardware support 3) 选择 ATECC608A 芯片类型: @@ -231,13 +231,40 @@ ESP-TLS 支持在 ESP32 系列芯片上使用 ATECC608A 加密芯片,但必须 如需了解更多 ATECC608A 芯片类型,或需了解如何获取连接到特定 ESP 模块的 ATECC608A 芯片类型,请参阅 `ATECC608A 芯片类型 `_。 -4) 在 :cpp:type:`esp_tls_cfg_t` 中提供以下配置,在 ESP-TLS 中启用 ATECC608A: +4) 初始化 PSA Crypto,导入 ATECC608A 密钥,并通过 :cpp:type:`esp_key_config_t` 配置 ESP-TLS 使用: .. code-block:: c + #include "psa/crypto.h" + #include "psa_crypto_driver_secure_element.h" + #include "psa_crypto_driver_secure_element_contexts.h" + #include "esp_key_config.h" + + /* 将 ATECC608A 密钥引用导入 PSA */ + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_SECURE_ELEMENT_VOLATILE); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&key_attr, 256); + + secure_element_opaque_key_t opaque_key = { + .slot_id = 0, /* ATECC608A 上的私钥槽位 */ + }; + + psa_key_id_t psa_key_id; + psa_import_key(&key_attr, (const uint8_t *)&opaque_key, + sizeof(opaque_key), &psa_key_id); + + /* 配置 ESP-TLS 使用 PSA 密钥 */ + esp_key_config_t key_config = { + .source = ESP_KEY_SOURCE_PSA, + .psa.key_id = psa_key_id, + }; + esp_tls_cfg_t cfg = { /* 其他配置选项 */ - .use_secure_element = true, + .client_key = &key_config, }; .. only:: SOC_DIG_SIGN_SUPPORTED From b6947348c6cdc6d6367812bfc5f06bea99b8eb9f Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 8 Apr 2026 18:39:53 +0530 Subject: [PATCH 03/12] docs(esp-tls): Update documentation for unified key interface and SE driver Update esp_tls, esp_http_client docs and migration guide to reflect the new esp_key_config_t interface and secure element PSA driver. (cherry picked from commit 37808e2386906e1dcf999098b2ebb3eb067d1313) --- .../api-reference/protocols/esp_http_client.rst | 11 ++++++++--- docs/en/api-reference/protocols/esp_tls.rst | 2 ++ .../release-6.x/6.0/protocols.rst | 17 +++++++++++++++++ .../api-reference/protocols/esp_http_client.rst | 11 ++++++++--- docs/zh_CN/api-reference/protocols/esp_tls.rst | 2 ++ .../release-6.x/6.0/protocols.rst | 17 +++++++++++++++++ 6 files changed, 54 insertions(+), 6 deletions(-) diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index abcd1acd763..c9fe9f9ec34 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -36,13 +36,18 @@ To allow ESP HTTP client to take full advantage of persistent connections, one s Use Secure Element (ATECC608) for TLS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -A secure element (ATECC608) can be also used for the underlying TLS connection in the HTTP client connection. Please refer to the **ATECC608A (Secure Element) with ESP-TLS** section in the :doc:`ESP-TLS documentation ` for more details. The secure element support has to be first enabled in menuconfig through :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT`. Then the HTTP client can be configured to use secure element as follows: +A secure element (ATECC608) can be used for the underlying TLS connection in the HTTP client connection via the PSA Crypto opaque driver interface. Please refer to the **ATECC608A (Secure Element) with ESP-TLS** section in the :doc:`ESP-TLS documentation ` for details on setting up the PSA key. Then configure the HTTP client to use the secure element via the ``client_key`` field in :cpp:type:`esp_tls_cfg_t`: .. code-block:: c + esp_key_config_t key_config = { + .source = ESP_KEY_SOURCE_PSA, + .psa.key_id = psa_key_id, /* obtained via psa_import_key() */ + }; + esp_http_client_config_t cfg = { - /* other configurations options */ - .use_secure_element = true, + /* other configuration options */ + .client_key = &key_config, }; .. only:: SOC_ECDSA_SUPPORTED diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index a4affa7f260..8e97b8d33fa 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -204,6 +204,8 @@ To use a custom TLS stack in your project, follow these steps: * For detailed function signatures and requirements, see :component_file:`esp-tls/esp_tls_custom_stack.h`. +.. _atecc608a-with-esp-tls: + ATECC608A (Secure Element) with ESP-TLS -------------------------------------------------- diff --git a/docs/en/migration-guides/release-6.x/6.0/protocols.rst b/docs/en/migration-guides/release-6.x/6.0/protocols.rst index 8495cc57ff0..29b74474ff1 100644 --- a/docs/en/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/en/migration-guides/release-6.x/6.0/protocols.rst @@ -104,6 +104,23 @@ The deprecated :cpp:func:`esp_tls_conn_http_new` function has been removed. Use The new API requires you to create the :cpp:type:`esp_tls_t` structure using :cpp:func:`esp_tls_init` and provides better control over the connection process. +Unified Private Key Interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``use_secure_element`` field has been removed from :cpp:type:`esp_tls_cfg`, :cpp:type:`esp_tls_cfg_server`, and :cpp:type:`httpd_ssl_config`. The ATECC608A secure element and all other hardware-backed key sources (DS peripheral, ECDSA peripheral, Key Manager) are now accessed through a unified :cpp:type:`esp_key_config_t` interface via PSA Crypto key IDs. + +**Migration Steps** + +1. Replace ``use_secure_element = true`` with the new :cpp:type:`esp_key_config_t` using ``ESP_KEY_SOURCE_PSA`` and a PSA key ID obtained from ``psa_import_key()``. + +2. The ``atcab_init()`` call is no longer performed internally by ESP-TLS. Applications using the ATECC608A must ensure the secure element is initialized at the application level before use. Refer to the `esp-cryptoauthlib documentation `_ for details. + +3. The ``esp_transport_ssl_use_secure_element()`` function has been removed from ``tcp_transport``. Use ``esp_transport_ssl_set_client_key_config()`` instead. + +4. The Kconfig options for the secure element driver have been consolidated from ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN`` / ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY`` into a single ``CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED``. The old names are automatically mapped via ``sdkconfig.rename``. + +For detailed usage examples, see :ref:`atecc608a-with-esp-tls`. + ESP HTTP Server --------------- diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst index 9c5bb667429..95b44a33d64 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -35,13 +35,18 @@ HTTP 基本请求 为 TLS 使用安全元件 (ATECC608) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -安全元件 (ATECC608) 也可用于 HTTP 客户端连接中的底层 TLS 连接。详细内容请参考 :doc:`ESP-TLS 文档 ` 中的 **ESP-TLS 中的 ATECC608A(安全元件)支持** 小节。如需支持安全元素,必须首先在 menuconfig 中通过 :ref:`CONFIG_ESP_TLS_USE_SECURE_ELEMENT` 对其进行启用,此后,可配置 HTTP 客户端使用安全元素,如下所示: +安全元件 (ATECC608) 可通过 PSA Crypto 不透明驱动接口用于 HTTP 客户端连接中的底层 TLS 连接。有关设置 PSA 密钥的详细内容,请参考 :doc:`ESP-TLS 文档 ` 中的 **ESP-TLS 中的 ATECC608A(安全元件)** 小节。然后通过 :cpp:type:`esp_tls_cfg_t` 中的 ``client_key`` 字段配置 HTTP 客户端使用安全元件: .. code-block:: c + esp_key_config_t key_config = { + .source = ESP_KEY_SOURCE_PSA, + .psa.key_id = psa_key_id, /* 通过 psa_import_key() 获取 */ + }; + esp_http_client_config_t cfg = { - /* other configurations options */ - .use_secure_element = true, + /* 其他配置选项 */ + .client_key = &key_config, }; .. only:: SOC_ECDSA_SUPPORTED diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index 5d66d8d7059..b01bfc0253b 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -204,6 +204,8 @@ ESP-TLS 组件支持通过 :cpp:func:`esp_tls_register_stack` API 注册自定 * 更多函数签名和要求,请参阅 :component_file:`esp-tls/esp_tls_custom_stack.h`。 +.. _atecc608a-with-esp-tls: + ESP-TLS 中的 ATECC608A(安全元件) ----------------------------------------- diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst index 07e67ed91f0..f1eb34a1795 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst @@ -104,6 +104,23 @@ ESP-TLS 已移除内置的 wolfSSL TLS 协议栈支持。使用 wolfSSL 的用 新 API 需要您使用 :cpp:func:`esp_tls_init` 创建 :cpp:type:`esp_tls_t` 结构,并提供对连接过程的更好控制。 +统一私钥接口 +~~~~~~~~~~~~~ + +:cpp:type:`esp_tls_cfg`、:cpp:type:`esp_tls_cfg_server` 和 :cpp:type:`httpd_ssl_config` 中的 ``use_secure_element`` 字段已被移除。ATECC608A 安全元件和所有其他硬件支持的密钥源(DS 外设、ECDSA 外设、密钥管理器)现在通过统一的 :cpp:type:`esp_key_config_t` 接口和 PSA Crypto 密钥 ID 来访问。 + +**迁移步骤** + +1. 将 ``use_secure_element = true`` 替换为使用 ``ESP_KEY_SOURCE_PSA`` 的新 :cpp:type:`esp_key_config_t`,以及通过 ``psa_import_key()`` 获取的 PSA 密钥 ID。 + +2. ``atcab_init()`` 调用不再由 ESP-TLS 内部执行。使用 ATECC608A 的应用程序必须确保在使用前在应用层初始化安全元件。详情请参阅 `esp-cryptoauthlib 文档 `_。 + +3. ``esp_transport_ssl_use_secure_element()`` 函数已从 ``tcp_transport`` 中移除。请改用 ``esp_transport_ssl_set_client_key_config()``。 + +4. 安全元件驱动的 Kconfig 选项已从 ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN`` / ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY`` 合并为 ``CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED``。旧名称通过 ``sdkconfig.rename`` 自动映射。 + +详细使用示例请参阅 :ref:`atecc608a-with-esp-tls`。 + ESP HTTP 服务器 --------------- From 9b185eba9f474a4a5938ef2f64c93321ce49ae8c Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Thu, 9 Apr 2026 17:14:41 +0530 Subject: [PATCH 04/12] fix(esp-tls): Use runtime assignment for static key config length in examples Linker symbol differences (prvtkey_pem_end - prvtkey_pem_start) are not compile-time constants and cannot be used in static initializers. (cherry picked from commit 4196734d1a5ddbb10e5fc7a3949ed53305ce1f3f) --- examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c | 2 +- examples/protocols/https_server/simple/main/main.c | 2 +- .../protocols/https_server/wss_server/main/wss_server_example.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c index 084e80a1249..39f0ea31d0a 100644 --- a/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c +++ b/examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c @@ -244,9 +244,9 @@ void start_esp_local_ctrl_service(void) .source = ESP_KEY_SOURCE_BUFFER, .buffer = { .data = prvtkey_pem_start, - .len = prvtkey_pem_end - prvtkey_pem_start, } }; + server_key.buffer.len = prvtkey_pem_end - prvtkey_pem_start; https_conf.server_key = &server_key; #else httpd_config_t http_conf = HTTPD_DEFAULT_CONFIG(); diff --git a/examples/protocols/https_server/simple/main/main.c b/examples/protocols/https_server/simple/main/main.c index deb33c722e1..0ae2613138f 100644 --- a/examples/protocols/https_server/simple/main/main.c +++ b/examples/protocols/https_server/simple/main/main.c @@ -211,9 +211,9 @@ static httpd_handle_t start_webserver(void) .source = ESP_KEY_SOURCE_BUFFER, .buffer = { .data = prvtkey_pem_start, - .len = prvtkey_pem_end - prvtkey_pem_start, } }; + server_key.buffer.len = prvtkey_pem_end - prvtkey_pem_start; conf.server_key = &server_key; #if CONFIG_EXAMPLE_ENABLE_HTTPS_SERVER_CUSTOM_CIPHERSUITES diff --git a/examples/protocols/https_server/wss_server/main/wss_server_example.c b/examples/protocols/https_server/wss_server/main/wss_server_example.c index b3c529f06f1..b6b31c36312 100644 --- a/examples/protocols/https_server/wss_server/main/wss_server_example.c +++ b/examples/protocols/https_server/wss_server/main/wss_server_example.c @@ -216,9 +216,9 @@ static httpd_handle_t start_wss_echo_server(void) .source = ESP_KEY_SOURCE_BUFFER, .buffer = { .data = prvtkey_pem_start, - .len = prvtkey_pem_end - prvtkey_pem_start, } }; + server_key.buffer.len = prvtkey_pem_end - prvtkey_pem_start; conf.server_key = &server_key; esp_err_t ret = httpd_ssl_start(&server, &conf); From 72b2e4f4fd7e0b85f9f9c62112abcc40d7b1327c Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Fri, 22 May 2026 13:41:08 +0530 Subject: [PATCH 05/12] fix(esp-tls): address MR review comments for SE PSA driver - esp_tls_mbedtls: require cert when PSA-backed server/client key is set - esp_tls_mbedtls: drop redundant pk_init/x509_crt_init (calloc handles it) - psa SE driver: copy callbacks/opaque_key by value (no lifetime coupling) - psa SE driver: replace atomic CAS with simple null check on register - psa SE driver: use sig_len from sign callback with bounds validation - psa SE driver: validate pubkey_len returned by export_pubkey callback - psa SE driver: check hash sub-alg in RSA PKCS1V15 branch of validate_request - psa SE driver: align secure_element_register_callbacks doc with value-copy impl - esp_https_server: initialize server_key in HTTPD_SSL_CONFIG_DEFAULT - mbedtls: move SECURE_ELEMENT_DRIVER_ENABLED to esp_config.h for parity with ESP_ECDSA_DRIVER_ENABLED; drop target_compile_definitions - docs: fix esp_tls_cfg_t -> esp_http_client_config_t cross-reference - docs: check psa_import_key() status in ESP-TLS PSA example - hints/error_output: point at CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED (cherry picked from commit 08b567ef3bd794d225838c0769005038abce455a) --- components/esp-tls/esp_tls_mbedtls.c | 68 +++++++++---------- components/esp-tls/hints.yml | 2 +- components/esp-tls/test_apps/README.md | 4 +- .../include/esp_https_server.h | 1 + components/mbedtls/CMakeLists.txt | 2 - .../mbedtls/port/include/mbedtls/esp_config.h | 5 +- .../psa_crypto_driver_secure_element.h | 8 ++- ...sa_crypto_driver_secure_element_contexts.h | 2 +- .../psa_crypto_driver_secure_element.c | 51 ++++++++++---- .../protocols/esp_http_client.rst | 2 +- docs/en/api-reference/protocols/esp_tls.rst | 9 ++- .../protocols/esp_http_client.rst | 2 +- .../zh_CN/api-reference/protocols/esp_tls.rst | 8 ++- tools/test_idf_py/error_output.yml | 2 +- 14 files changed, 100 insertions(+), 66 deletions(-) diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 5c0050091b8..9d62b5debea 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -763,8 +763,11 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) return esp_ret; } } else if (cfg->server_key != NULL && cfg->server_key->source == ESP_KEY_SOURCE_PSA) { + if (cfg->servercert_buf == NULL) { + ESP_LOGE(TAG, "Server certificate is required when using a PSA-backed server key"); + return ESP_ERR_INVALID_ARG; + } mbedtls_svc_key_id_t key_id = cfg->server_key->psa.key_id; - mbedtls_pk_init(&tls->serverkey); ret = mbedtls_pk_wrap_psa(&tls->serverkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); @@ -772,22 +775,19 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; } - if (cfg->servercert_buf != NULL) { - mbedtls_x509_crt_init(&tls->servercert); - ret = mbedtls_x509_crt_parse(&tls->servercert, cfg->servercert_buf, cfg->servercert_bytes); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; - } - ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->servercert, &tls->serverkey); - if (ret != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; - } + ret = mbedtls_x509_crt_parse(&tls->servercert, cfg->servercert_buf, cfg->servercert_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->servercert, &tls->serverkey); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; } } else if (cfg->use_ecdsa_peripheral) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN @@ -1026,8 +1026,11 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t return esp_ret; } } else if (cfg->client_key != NULL && cfg->client_key->source == ESP_KEY_SOURCE_PSA) { + if (cfg->clientcert_buf == NULL) { + ESP_LOGE(TAG, "Client certificate is required when using a PSA-backed client key"); + return ESP_ERR_INVALID_ARG; + } mbedtls_svc_key_id_t key_id = cfg->client_key->psa.key_id; - mbedtls_pk_init(&tls->clientkey); ret = mbedtls_pk_wrap_psa(&tls->clientkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); @@ -1035,22 +1038,19 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; } - if (cfg->clientcert_buf != NULL) { - mbedtls_x509_crt_init(&tls->clientcert); - ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_buf, cfg->clientcert_bytes); - if (ret < 0) { - ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; - } - ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); - if (ret != 0) { - ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); - mbedtls_print_error_msg(ret); - ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); - return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; - } + ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_buf, cfg->clientcert_bytes); + if (ret < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED; + } + ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret); + return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED; } } else if (cfg->ds_data != NULL) { #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL diff --git a/components/esp-tls/hints.yml b/components/esp-tls/hints.yml index 6cf22e110ec..44263c1d148 100644 --- a/components/esp-tls/hints.yml +++ b/components/esp-tls/hints.yml @@ -3,4 +3,4 @@ hint: "The struct 'esp_tls_t' has now been made private - its elements can be only be accessed/modified through respective getter/setter functions. Please refer to the migration guide for more information." - re: "fatal error: .*atca_mbedtls_wrap\\.h: No such file or directory" - hint: "To use CONFIG_ESP_TLS_USE_SECURE_ELEMENT option, please install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" + hint: "To use the ATECC608A secure element, enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED and install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" diff --git a/components/esp-tls/test_apps/README.md b/components/esp-tls/test_apps/README.md index 67844e9673a..d76348d52c2 100644 --- a/components/esp-tls/test_apps/README.md +++ b/components/esp-tls/test_apps/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32-C3 | -| ----------------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 58d568e21ea..288d1bbf72d 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -219,6 +219,7 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; HTTPD_SSL_CONFIG_CLIENT_AUTH_OPTIONAL_INIT \ .prvtkey_pem = NULL, \ .prvtkey_len = 0, \ + .server_key = NULL, \ .use_ecdsa_peripheral = false, \ .ecdsa_key_efuse_blk = 0, \ .ecdsa_key_efuse_blk_high = 0, \ diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 7eb0369b468..8e967f9b416 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -481,8 +481,6 @@ if(CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c") target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include") - target_compile_definitions(tfpsacrypto PRIVATE - SECURE_ELEMENT_DRIVER_ENABLED) endif() if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU") diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index fd67f7bccb3..596a30faddb 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -267,8 +267,9 @@ #endif #endif -/* SECURE_ELEMENT_DRIVER_ENABLED is set via target_compile_definitions in - * CMakeLists.txt when CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED is set. */ +#ifdef CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED +#define SECURE_ELEMENT_DRIVER_ENABLED +#endif #ifdef CONFIG_MBEDTLS_HARDWARE_ECC #ifdef CONFIG_MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h index 6a0831ba0ab..665cc56855c 100644 --- a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h @@ -113,10 +113,12 @@ typedef struct { * @brief Register secure element callbacks * * Must be called once during application initialization, before any PSA - * operations targeting PSA_KEY_LOCATION_SECURE_ELEMENT. Uses atomic - * compare-and-swap so only the first call succeeds. + * operations targeting PSA_KEY_LOCATION_SECURE_ELEMENT. Only the first + * call succeeds; subsequent calls return PSA_ERROR_BAD_STATE. * - * @param callbacks Pointer to callback table (must remain valid for program lifetime) + * @param callbacks Pointer to callback table. The contents are copied + * internally, so the struct need not remain valid after + * this call returns. * @return PSA_SUCCESS on success * @return PSA_ERROR_BAD_STATE if callbacks were already registered * @return PSA_ERROR_INVALID_ARGUMENT if callbacks is NULL diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h index 351e513fa01..da7e236b022 100644 --- a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element_contexts.h @@ -56,7 +56,7 @@ typedef struct { uint8_t sha[SECURE_ELEMENT_MAX_KEY_BYTES]; size_t key_len; size_t sha_len; - secure_element_opaque_key_t *opaque_key; + secure_element_opaque_key_t opaque_key; unsigned int alg; } secure_element_opaque_sign_hash_operation_t; diff --git a/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c b/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c index 351dc6348bd..91456dfd443 100644 --- a/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c +++ b/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c @@ -18,10 +18,9 @@ */ #include -#include #include "sdkconfig.h" -#ifdef SECURE_ELEMENT_DRIVER_ENABLED +#ifdef CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED #include "esp_log.h" #include "psa_crypto_driver_secure_element.h" @@ -30,8 +29,10 @@ static const char *TAG = "psa_crypto_driver_secure_element"; #define UNCOMPRESSED_POINT_FORMAT 0x04 -/* Runtime-registered SE callbacks (set once via secure_element_register_callbacks) */ -static const secure_element_callbacks_t *s_se_callbacks = NULL; +/* Runtime-registered SE callbacks (set once via secure_element_register_callbacks). + * We keep a value copy so the caller's struct lifetime does not matter. */ +static secure_element_callbacks_t s_se_callbacks; +static const secure_element_callbacks_t *s_se_callbacks_ptr = NULL; psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t *callbacks) { @@ -44,14 +45,14 @@ psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t return PSA_ERROR_INVALID_ARGUMENT; } - /* Atomic compare-and-swap: only the first registration succeeds */ - const secure_element_callbacks_t *expected = NULL; - if (!atomic_compare_exchange_strong((volatile _Atomic(const secure_element_callbacks_t *) *)&s_se_callbacks, - &expected, callbacks)) { + if (s_se_callbacks_ptr != NULL) { ESP_LOGE(TAG, "Secure element callbacks already registered"); return PSA_ERROR_BAD_STATE; } + s_se_callbacks = *callbacks; + s_se_callbacks_ptr = &s_se_callbacks; + return PSA_SUCCESS; } @@ -60,7 +61,7 @@ psa_status_t secure_element_register_callbacks(const secure_element_callbacks_t */ static inline const secure_element_callbacks_t *se_get_callbacks(void) { - return s_se_callbacks; + return s_se_callbacks_ptr; } /** @@ -93,6 +94,11 @@ static psa_status_t validate_request(psa_algorithm_t alg, const psa_key_attribut if (!PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { return PSA_ERROR_NOT_SUPPORTED; } + /* If registered with a specific hash, check it matches */ + psa_algorithm_t reg_hash = PSA_ALG_SIGN_GET_HASH(registered_alg); + if (reg_hash != PSA_ALG_ANY_HASH && reg_hash != PSA_ALG_SIGN_GET_HASH(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } } else if (registered_alg != alg) { return PSA_ERROR_NOT_SUPPORTED; } @@ -336,7 +342,7 @@ psa_status_t secure_element_opaque_sign_hash_start( memset(operation, 0, sizeof(secure_element_opaque_sign_hash_operation_t)); operation->key_len = component_len; memcpy(operation->sha, hash, component_len); - operation->opaque_key = (secure_element_opaque_key_t *) key_buffer; + memcpy(&operation->opaque_key, key_buffer, sizeof(secure_element_opaque_key_t)); operation->alg = alg; operation->sha_len = hash_length; @@ -367,7 +373,7 @@ psa_status_t secure_element_opaque_sign_hash_complete( /* Sign using registered SE callback */ uint8_t sig[2 * SECURE_ELEMENT_MAX_KEY_BYTES]; size_t sig_len = 0; - psa_status_t status = cbs->sign(operation->opaque_key->slot_id, + psa_status_t status = cbs->sign(operation->opaque_key.slot_id, operation->sha, operation->sha_len, sig, sizeof(sig), &sig_len); @@ -376,9 +382,18 @@ psa_status_t secure_element_opaque_sign_hash_complete( return status; } + if (sig_len == 0 || sig_len > sizeof(sig)) { + ESP_LOGE(TAG, "SE returned invalid signature length: %zu", sig_len); + return PSA_ERROR_GENERIC_ERROR; + } + + if (sig_len > signature_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + /* Copy signature to output (R || S format, big-endian - matches PSA) */ - memcpy(signature, sig, 2 * component_len); - *signature_length = 2 * component_len; + memcpy(signature, sig, sig_len); + *signature_length = sig_len; return PSA_SUCCESS; } @@ -463,6 +478,14 @@ psa_status_t secure_element_opaque_export_public_key( return status; } + /* Callback must have written exactly 2 * key_len bytes (X || Y) - reject anything else + * to avoid copying uninitialized stack memory into the caller's buffer. */ + if (pubkey_len != 2 * key_len) { + ESP_LOGE(TAG, "SE export_pubkey returned %u bytes, expected %u", + (unsigned)pubkey_len, (unsigned)(2 * key_len)); + return PSA_ERROR_HARDWARE_FAILURE; + } + /* Format: uncompressed point (0x04 followed by x and y coordinates) */ data[0] = UNCOMPRESSED_POINT_FORMAT; memcpy(data + 1, pubkey, key_len); /* X coordinate */ @@ -484,4 +507,4 @@ size_t secure_element_opaque_size_function( return sizeof(secure_element_opaque_key_t); } -#endif /* SECURE_ELEMENT_DRIVER_ENABLED */ +#endif /* CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED */ diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index c9fe9f9ec34..b3e157b60e0 100644 --- a/docs/en/api-reference/protocols/esp_http_client.rst +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -36,7 +36,7 @@ To allow ESP HTTP client to take full advantage of persistent connections, one s Use Secure Element (ATECC608) for TLS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -A secure element (ATECC608) can be used for the underlying TLS connection in the HTTP client connection via the PSA Crypto opaque driver interface. Please refer to the **ATECC608A (Secure Element) with ESP-TLS** section in the :doc:`ESP-TLS documentation ` for details on setting up the PSA key. Then configure the HTTP client to use the secure element via the ``client_key`` field in :cpp:type:`esp_tls_cfg_t`: +A secure element (ATECC608) can be used for the underlying TLS connection in the HTTP client connection via the PSA Crypto opaque driver interface. Please refer to the **ATECC608A (Secure Element) with ESP-TLS** section in the :doc:`ESP-TLS documentation ` for details on setting up the PSA key. Then configure the HTTP client to use the secure element via the ``client_key`` field in :cpp:type:`esp_http_client_config_t`: .. code-block:: c diff --git a/docs/en/api-reference/protocols/esp_tls.rst b/docs/en/api-reference/protocols/esp_tls.rst index 8e97b8d33fa..6b5500f0629 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -255,8 +255,13 @@ To enable the secure element support, and use it in your project for TLS connect }; psa_key_id_t psa_key_id; - psa_import_key(&key_attr, (const uint8_t *)&opaque_key, - sizeof(opaque_key), &psa_key_id); + psa_status_t status = psa_import_key(&key_attr, (const uint8_t *)&opaque_key, + sizeof(opaque_key), &psa_key_id); + if (status != PSA_SUCCESS) { + /* Handle error - typically means the SE callbacks are not registered + * or the attributes are invalid. */ + return; + } /* Configure ESP-TLS to use the PSA key */ esp_key_config_t key_config = { diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst index 95b44a33d64..057eed20cb0 100644 --- a/docs/zh_CN/api-reference/protocols/esp_http_client.rst +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -35,7 +35,7 @@ HTTP 基本请求 为 TLS 使用安全元件 (ATECC608) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -安全元件 (ATECC608) 可通过 PSA Crypto 不透明驱动接口用于 HTTP 客户端连接中的底层 TLS 连接。有关设置 PSA 密钥的详细内容,请参考 :doc:`ESP-TLS 文档 ` 中的 **ESP-TLS 中的 ATECC608A(安全元件)** 小节。然后通过 :cpp:type:`esp_tls_cfg_t` 中的 ``client_key`` 字段配置 HTTP 客户端使用安全元件: +安全元件 (ATECC608) 可通过 PSA Crypto 不透明驱动接口用于 HTTP 客户端连接中的底层 TLS 连接。有关设置 PSA 密钥的详细内容,请参考 :doc:`ESP-TLS 文档 ` 中的 **ESP-TLS 中的 ATECC608A(安全元件)** 小节。然后通过 :cpp:type:`esp_http_client_config_t` 中的 ``client_key`` 字段配置 HTTP 客户端使用安全元件: .. code-block:: c diff --git a/docs/zh_CN/api-reference/protocols/esp_tls.rst b/docs/zh_CN/api-reference/protocols/esp_tls.rst index b01bfc0253b..1967aed1cae 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -255,8 +255,12 @@ ESP-TLS 支持通过 PSA Crypto 不透明驱动接口在 ESP32 系列芯片上 }; psa_key_id_t psa_key_id; - psa_import_key(&key_attr, (const uint8_t *)&opaque_key, - sizeof(opaque_key), &psa_key_id); + psa_status_t status = psa_import_key(&key_attr, (const uint8_t *)&opaque_key, + sizeof(opaque_key), &psa_key_id); + if (status != PSA_SUCCESS) { + /* 处理错误 - 通常表示安全元件回调未注册或属性无效。 */ + return; + } /* 配置 ESP-TLS 使用 PSA 密钥 */ esp_key_config_t key_config = { diff --git a/tools/test_idf_py/error_output.yml b/tools/test_idf_py/error_output.yml index 3cc548d0be3..6512c615f27 100644 --- a/tools/test_idf_py/error_output.yml +++ b/tools/test_idf_py/error_output.yml @@ -50,7 +50,7 @@ "HINT: The component 'component' could not be found. This could be because: component name was misspelled, the component was not added to the build, the component has been moved to the IDF component manager, the component has been removed and refactored into some other component or the component may not be supported by the selected target.\nPlease look out for component in 'https://components.espressif.com' and add using 'idf.py add-dependency' command.\nRefer to the migration guide for more details about moved components.\nRefer to the build-system guide for more details about how components are found and included in the build." 'fatal error: tmp/atca_mbedtls_wrap.h: No such file or directory\n': - "HINT: To use CONFIG_ESP_TLS_USE_SECURE_ELEMENT option, please install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" + "HINT: To use the ATECC608A secure element, enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED and install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" 'fatal error: brownout.h: No such file or directory\n': 'HINT: The Brownout API (functions/types/macros prefixed with "esp_brownout") has been made into a private API. If users still require usage of the Brownout API (though this is not recommended), it can be included via #include "esp_private/brownout.h".' From 89af3ad342ba36ad1036748514fce5845060b2d8 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Mon, 25 May 2026 20:28:59 +0530 Subject: [PATCH 06/12] fix(esp-tls): call mbedtls_pk_init before mbedtls_pk_wrap_psa in PSA key paths Per mbedTLS API contract, mbedtls_pk_context must be explicitly initialized with mbedtls_pk_init() before calling mbedtls_pk_wrap_psa(). Add the missing init calls for both the server_key and client_key PSA-backed key code paths. (cherry picked from commit 005072c87e7f9742e61b3ad8e873d8195fe0b73c) --- components/esp-tls/esp_tls_mbedtls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 9d62b5debea..c53fff5a033 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -768,6 +768,7 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) return ESP_ERR_INVALID_ARG; } mbedtls_svc_key_id_t key_id = cfg->server_key->psa.key_id; + mbedtls_pk_init(&tls->serverkey); ret = mbedtls_pk_wrap_psa(&tls->serverkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); @@ -1031,6 +1032,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t return ESP_ERR_INVALID_ARG; } mbedtls_svc_key_id_t key_id = cfg->client_key->psa.key_id; + mbedtls_pk_init(&tls->clientkey); ret = mbedtls_pk_wrap_psa(&tls->clientkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); From ca9de76220799cb25c508f8d2f9c7bdff3b3ab9d Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 26 May 2026 19:12:49 +0530 Subject: [PATCH 07/12] fix(esp-tls): correct test_apps README to match manifest target restriction .build-test-rules.yml restricts esp-tls test_apps to esp32c3 only. Commit 19a544203b9 accidentally expanded the README to all targets. (cherry picked from commit b7f53c3868698437073eb2cbe0accc9f8c91d0fd) --- components/esp-tls/test_apps/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp-tls/test_apps/README.md b/components/esp-tls/test_apps/README.md index d76348d52c2..67844e9673a 100644 --- a/components/esp-tls/test_apps/README.md +++ b/components/esp-tls/test_apps/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | +| Supported Targets | ESP32-C3 | +| ----------------- | -------- | From 1a68c431a053ea316d3732fc6887e842fc7d3636 Mon Sep 17 00:00:00 2001 From: Mike Szczys Date: Fri, 26 Jun 2026 13:16:01 -0500 Subject: [PATCH 08/12] fix(esp-tls): only destroy volatile keys in DS/ECDSA cleanup The DS/ECDSA cleanup added in 8cb64703 is intended for volatile PSA keys created internally by the DS and ECDSA peripheral paths. Ensure that during the cleanup, PSA_KEY_LIFETIME_IS_VOLATILE() is checked to avoid destroying keys the user has added persistently to PSA. This resolves an issue in the next commit (adding support for clientkey_psa_id) where a user passes a PSA key id that is then silently destroyed if CONFIG_ESP_TLS_USE_DS_PERIPHERAL or CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN happen to be defined. Signed-off-by: Mike Szczys (cherry picked from commit da51d6901342a7f4fd9ce61219f9c92d351c971c) (cherry picked from commit f68cfbf8d4967a2fbf279b8158258763b98b2c11) --- components/esp-tls/esp_tls_mbedtls.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index c53fff5a033..9dafca9bf70 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -489,11 +489,22 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) * before calling mbedtls_pk_free(). mbedtls_pk_wrap_psa() sets the pk_info * to mbedtls_{rsa,ecdsa}_opaque_info, both of which have type * MBEDTLS_PK_OPAQUE — so a single check covers both DS and ECDSA paths. - * clientkey and serverkey share storage via union, so one branch suffices. */ + * clientkey and serverkey share storage via union, so one branch suffices. + * + * Only destroy volatile keys created internally by the DS/ECDSA peripheral + * paths. Keys wrapped from an external clientkey_psa_id are caller-owned + * (typically persistent) and must not be destroyed here. */ #if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_OPAQUE) { if (tls->clientkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) { - psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); + psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT; + if (psa_get_key_attributes(tls->clientkey.MBEDTLS_PRIVATE(priv_id), + &attrs) == PSA_SUCCESS) { + if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(&attrs))) { + psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); + } + psa_reset_key_attributes(&attrs); + } tls->clientkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL; } } From 626725749ae9153c3d43652c8f6d3dc6a48b05be Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Mon, 29 Jun 2026 15:48:44 +0530 Subject: [PATCH 09/12] fix(esp-tls): track opaque PSA key ownership and cover the secure-element path Replace the key-lifetime check with explicit ownership tracking so a caller-supplied volatile PSA key is also preserved on cleanup, and drop the DS/HARDWARE_ECDSA compile guard so the ESP_KEY_SOURCE_PSA path is released on pure secure-element builds. (cherry picked from commit 7cdd0b59607af81b32e72406c3cbe26e0e449c0b) --- components/esp-tls/esp_tls_mbedtls.c | 39 +++++++++---------- .../esp-tls/private_include/esp_tls_private.h | 4 ++ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 9dafca9bf70..dfede2a2118 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -484,31 +484,28 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) mbedtls_x509_crt_free(&tls->cacert); mbedtls_x509_crt_free(&tls->clientcert); - /* For opaque keys (DS peripheral, hardware ECDSA), mbedtls_pk_free() does - * not destroy the PSA key — ownership is external. Destroy it manually - * before calling mbedtls_pk_free(). mbedtls_pk_wrap_psa() sets the pk_info - * to mbedtls_{rsa,ecdsa}_opaque_info, both of which have type - * MBEDTLS_PK_OPAQUE — so a single check covers both DS and ECDSA paths. - * clientkey and serverkey share storage via union, so one branch suffices. - * - * Only destroy volatile keys created internally by the DS/ECDSA peripheral - * paths. Keys wrapped from an external clientkey_psa_id are caller-owned - * (typically persistent) and must not be destroyed here. */ -#if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) + /* For opaque keys, mbedtls_pk_free() does not release the underlying PSA + * key — ownership is tracked separately. Dispatch on ownership, not on the + * key lifetime: a caller-supplied key (ESP_KEY_SOURCE_PSA, e.g. a + * pre-provisioned secure element) is owned externally and must never be + * destroyed on connection close — at most purge it to drop the cached slot + * (a no-op for a volatile key). A key esp-tls created itself is always + * volatile and is destroyed to release its slot. mbedtls_pk_wrap_psa() sets + * the pk_info to mbedtls_{rsa,ecdsa}_opaque_info, both of type + * MBEDTLS_PK_OPAQUE, so one runtime check covers every opaque path (DS + * peripheral, hardware ECDSA, and caller-supplied PSA keys). clientkey and + * serverkey share storage via union, so one branch suffices. */ if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_OPAQUE) { - if (tls->clientkey.MBEDTLS_PRIVATE(priv_id) != PSA_KEY_ID_NULL) { - psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT; - if (psa_get_key_attributes(tls->clientkey.MBEDTLS_PRIVATE(priv_id), - &attrs) == PSA_SUCCESS) { - if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(&attrs))) { - psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); - } - psa_reset_key_attributes(&attrs); + psa_key_id_t kid = tls->clientkey.MBEDTLS_PRIVATE(priv_id); + if (kid != PSA_KEY_ID_NULL) { + if (tls->opaque_key_is_external) { + psa_purge_key(kid); + } else { + psa_destroy_key(kid); } tls->clientkey.MBEDTLS_PRIVATE(priv_id) = PSA_KEY_ID_NULL; } } -#endif mbedtls_pk_free(&tls->clientkey); mbedtls_ssl_config_free(&tls->conf); @@ -780,6 +777,7 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) } mbedtls_svc_key_id_t key_id = cfg->server_key->psa.key_id; mbedtls_pk_init(&tls->serverkey); + tls->opaque_key_is_external = true; ret = mbedtls_pk_wrap_psa(&tls->serverkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); @@ -1044,6 +1042,7 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t } mbedtls_svc_key_id_t key_id = cfg->client_key->psa.key_id; mbedtls_pk_init(&tls->clientkey); + tls->opaque_key_is_external = true; ret = mbedtls_pk_wrap_psa(&tls->clientkey, key_id); if (ret != 0) { ESP_LOGE(TAG, "mbedtls_pk_wrap_psa returned -0x%04X", -ret); diff --git a/components/esp-tls/private_include/esp_tls_private.h b/components/esp-tls/private_include/esp_tls_private.h index a90e5a26ecb..d35ecb915c1 100644 --- a/components/esp-tls/private_include/esp_tls_private.h +++ b/components/esp-tls/private_include/esp_tls_private.h @@ -52,6 +52,10 @@ struct esp_tls { mbedtls_pk_context serverkey; /*!< Container for the private key of the server certificate */ }; + + bool opaque_key_is_external; /*!< True when the opaque PSA client/server key was supplied + by the caller (ESP_KEY_SOURCE_PSA). Such keys are owned + externally and must never be destroyed on cleanup. */ #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN bool use_ecdsa_peripheral; /*!< Use the ECDSA peripheral for the private key operations. */ uint8_t ecdsa_efuse_blk; /*!< The efuse block number where the ECDSA key is stored. */ From 0688fe6f23994e1853624b2e17163a1f29de7f37 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Mon, 29 Jun 2026 17:45:42 +0530 Subject: [PATCH 10/12] fix(esp-tls): update secure element build hint for PSA integration (cherry picked from commit 5f1074045f66a0088859075d320b78aed0885935) --- components/esp-tls/hints.yml | 2 +- tools/test_idf_py/error_output.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp-tls/hints.yml b/components/esp-tls/hints.yml index 44263c1d148..ffbfcf9bab4 100644 --- a/components/esp-tls/hints.yml +++ b/components/esp-tls/hints.yml @@ -3,4 +3,4 @@ hint: "The struct 'esp_tls_t' has now been made private - its elements can be only be accessed/modified through respective getter/setter functions. Please refer to the migration guide for more information." - re: "fatal error: .*atca_mbedtls_wrap\\.h: No such file or directory" - hint: "To use the ATECC608A secure element, enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED and install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" + hint: "The cryptoauthlib mbedTLS wrapper (atca_mbedtls_wrap.h) is no longer used to integrate a secure element. Enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED, install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib', and provide the key via esp_key_config_t (ESP_KEY_SOURCE_PSA). Please refer to the migration guide for more information." diff --git a/tools/test_idf_py/error_output.yml b/tools/test_idf_py/error_output.yml index 6512c615f27..6a157709aef 100644 --- a/tools/test_idf_py/error_output.yml +++ b/tools/test_idf_py/error_output.yml @@ -50,7 +50,7 @@ "HINT: The component 'component' could not be found. This could be because: component name was misspelled, the component was not added to the build, the component has been moved to the IDF component manager, the component has been removed and refactored into some other component or the component may not be supported by the selected target.\nPlease look out for component in 'https://components.espressif.com' and add using 'idf.py add-dependency' command.\nRefer to the migration guide for more details about moved components.\nRefer to the build-system guide for more details about how components are found and included in the build." 'fatal error: tmp/atca_mbedtls_wrap.h: No such file or directory\n': - "HINT: To use the ATECC608A secure element, enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED and install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib'" + "HINT: The cryptoauthlib mbedTLS wrapper (atca_mbedtls_wrap.h) is no longer used to integrate a secure element. Enable CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED, install `esp-cryptoauthlib` using 'idf.py add-dependency espressif/esp-cryptoauthlib', and provide the key via esp_key_config_t (ESP_KEY_SOURCE_PSA). Please refer to the migration guide for more information." 'fatal error: brownout.h: No such file or directory\n': 'HINT: The Brownout API (functions/types/macros prefixed with "esp_brownout") has been made into a private API. If users still require usage of the Brownout API (though this is not recommended), it can be included via #include "esp_private/brownout.h".' From 49d1a84c0b0fa155b030d21a98cb6c5ac5ac09be Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Mon, 29 Jun 2026 17:58:16 +0530 Subject: [PATCH 11/12] docs(esp-tls): clarify caller owns the PSA key in esp_key_config_t (cherry picked from commit ed6f697ea81ee34a9d1b680456819ae9b36a1f0f) --- components/esp-tls/esp_tls.h | 8 ++++++-- components/esp-tls/esp_tls_mbedtls.c | 1 - components/mbedtls/sdkconfig.rename | 2 -- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 3d7596959ec..3232aef5d60 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -161,7 +161,9 @@ typedef struct esp_tls_cfg { const unsigned char *clientkey_pem_buf; /*!< Client key legacy name */ }; - const esp_key_config_t *client_key; /*!< Unified key config. Must remain valid for session lifetime */ + const esp_key_config_t *client_key; /*!< Unified key config. Must remain valid for session lifetime. + Any PSA key referenced here remains owned by the caller; ESP-TLS does not + destroy it on cleanup, so the application must release it with psa_destroy_key(). */ union { unsigned int clientkey_bytes; /*!< Size of client key pointed to by @@ -315,7 +317,9 @@ typedef struct esp_tls_cfg_server { const unsigned char *serverkey_pem_buf; /*!< Server key legacy name */ }; - const esp_key_config_t *server_key; /*!< Unified key config. Must remain valid for session lifetime */ + const esp_key_config_t *server_key; /*!< Unified key config. Must remain valid for session lifetime. + Any PSA key referenced here remains owned by the caller; ESP-TLS does not + destroy it on cleanup, so the application must release it with psa_destroy_key(). */ union { unsigned int serverkey_bytes; /*!< Size of server key pointed to by diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index dfede2a2118..20e0b9ecc19 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -476,7 +476,6 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) if (!tls) { return; } - if (tls->cacert_ptr != global_cacert) { mbedtls_x509_crt_free(tls->cacert_ptr); } diff --git a/components/mbedtls/sdkconfig.rename b/components/mbedtls/sdkconfig.rename index 580d93bb06f..704feb32cac 100644 --- a/components/mbedtls/sdkconfig.rename +++ b/components/mbedtls/sdkconfig.rename @@ -1,5 +1,3 @@ # Renamed ATCA/SE ECDSA options to generic secure element (v6.0) CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED -CONFIG_MBEDTLS_SE_HW_ECDSA_SIGN CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED -CONFIG_MBEDTLS_SE_HW_ECDSA_VERIFY CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED From 3e6429e881094205ca83edcfca0519f936b7fe63 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 15 Jul 2026 12:33:55 +0530 Subject: [PATCH 12/12] fix(esp-tls): Keep deprecated use_secure_element field for compatibility Restore the use_secure_element field in esp_tls_cfg_t, esp_tls_cfg_server_t and httpd_ssl_config_t, and esp_transport_ssl_use_secure_element(), as deprecated no-ops so that existing code keeps compiling. Setting them now fails at runtime with ESP_ERR_NOT_SUPPORTED, as the feature is accessed via the esp_key_config_t interface. To be removed in the next major release. No compile-time deprecation attribute on this release branch; the field and function stay warning-free here and carry only documentation notes. --- components/esp-tls/esp_tls.h | 14 ++++++++++++++ components/esp-tls/esp_tls_mbedtls.c | 18 ++++++++++++++++++ .../include/esp_https_server.h | 6 ++++++ components/esp_https_server/src/https_server.c | 9 +++++++++ .../tcp_transport/include/esp_transport_ssl.h | 12 ++++++++++++ components/tcp_transport/transport_ssl.c | 8 ++++++++ .../release-6.x/6.0/protocols.rst | 4 ++-- .../release-6.x/6.0/protocols.rst | 4 ++-- 8 files changed, 71 insertions(+), 4 deletions(-) diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 3232aef5d60..5f84f10813b 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -189,6 +189,13 @@ typedef struct esp_tls_cfg { underneath socket will be configured in non blocking mode after tls session is established */ + bool use_secure_element; /*!< @deprecated No longer functional; setting this to true + makes the connection fail with ESP_ERR_NOT_SUPPORTED. + Use `client_key` (esp_key_config_t) together with + CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. + Kept only for source compatibility; will be removed in + the next major release. */ + int timeout_ms; /*!< Network 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 @@ -340,6 +347,13 @@ typedef struct esp_tls_cfg_server { esp_tls_ecdsa_curve_t ecdsa_curve; /*!< ECDSA curve to use (SECP256R1 or SECP384R1) */ + bool use_secure_element; /*!< @deprecated No longer functional; setting this to true + makes the connection fail with ESP_ERR_NOT_SUPPORTED. + Use `server_key` (esp_key_config_t) together with + CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. + Kept only for source compatibility; will be removed in + the next major release. */ + 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 diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 20e0b9ecc19..81bbc099534 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -752,6 +752,15 @@ static esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) #endif // CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL } + /* use_secure_element is deprecated and non-functional: the cryptoauthlib + * mbedTLS-ALT integration is not compatible with the PSA-based mbedTLS. + * The field is kept for source compatibility only. */ + if (cfg->use_secure_element) { + ESP_LOGE(TAG, "use_secure_element is no longer supported. Use server_key (esp_key_config_t) with " + "CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. See the ESP-TLS migration guide."); + return ESP_ERR_NOT_SUPPORTED; + } + if (cfg->server_key != NULL && cfg->server_key->source == ESP_KEY_SOURCE_BUFFER) { /* Unified key config with buffer source */ esp_tls_pki_t pki = { @@ -1017,6 +1026,15 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #endif } + /* use_secure_element is deprecated and non-functional: the cryptoauthlib + * mbedTLS-ALT integration is not compatible with the PSA-based mbedTLS. + * The field is kept for source compatibility only. */ + if (cfg->use_secure_element) { + ESP_LOGE(TAG, "use_secure_element is no longer supported. Use client_key (esp_key_config_t) with " + "CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. See the ESP-TLS migration guide."); + return ESP_ERR_NOT_SUPPORTED; + } + if (cfg->client_key != NULL && cfg->client_key->source == ESP_KEY_SOURCE_BUFFER) { /* Unified key config with buffer source */ esp_tls_pki_t pki = { diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 288d1bbf72d..2c92b6c2dd6 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -132,6 +132,12 @@ struct httpd_ssl_config { /** Enable tls session tickets */ bool session_tickets; + /** @deprecated No longer functional; setting this to true makes server start fail with + * ESP_ERR_NOT_SUPPORTED. Use `server_key` (esp_key_config_t) together with + * CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. Kept only for source + * compatibility; will be removed in the next major release. */ + bool use_secure_element; + /** User callback for esp_https_server */ esp_https_server_user_cb *user_cb; diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index 2184228087a..0f9b7ace5d1 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -348,6 +348,15 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht #endif } + /* use_secure_element is deprecated and non-functional; it is kept only for + * source compatibility. */ + if (config->use_secure_element) { + ESP_LOGE(TAG, "use_secure_element is no longer supported. Use server_key (esp_key_config_t) with " + "CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. See the ESP-TLS migration guide."); + ret = ESP_ERR_NOT_SUPPORTED; + goto exit; + } + if (config->use_ecdsa_peripheral) { #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index b0ec044a305..546679299ee 100644 --- a/components/tcp_transport/include/esp_transport_ssl.h +++ b/components/tcp_transport/include/esp_transport_ssl.h @@ -206,6 +206,18 @@ void esp_transport_ssl_set_common_name(esp_transport_handle_t t, const char *com */ void esp_transport_ssl_set_ciphersuites_list(esp_transport_handle_t t, const int *ciphersuites_list); +/** + * @brief Set the ssl context to use secure element (atecc608a) for client(device) private key and certificate + * + * @deprecated No longer functional; the TLS connection will fail with ESP_ERR_NOT_SUPPORTED when + * this option is set. Use esp_transport_ssl_set_client_key_config() (esp_key_config_t) + * together with CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED instead. Kept only for + * source compatibility; will be removed in the next major release. + * + * @param t ssl transport + */ +void esp_transport_ssl_use_secure_element(esp_transport_handle_t t); + /** * @brief Set the ds_data handle in ssl context.(used for the digital signature operation) * diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index 0f01ebecb87..f3059d275c6 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -502,6 +502,14 @@ void esp_transport_ssl_set_ciphersuites_list(esp_transport_handle_t t, const int ssl->cfg.ciphersuites_list = ciphersuites_list; } +/* Deprecated and non-functional; kept only for source compatibility. Setting + * use_secure_element makes the connection fail with ESP_ERR_NOT_SUPPORTED. */ +void esp_transport_ssl_use_secure_element(esp_transport_handle_t t) +{ + GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t); + ssl->cfg.use_secure_element = true; +} + #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE void esp_transport_ssl_crt_bundle_attach(esp_transport_handle_t t, esp_err_t ((*crt_bundle_attach)(void *conf))) { diff --git a/docs/en/migration-guides/release-6.x/6.0/protocols.rst b/docs/en/migration-guides/release-6.x/6.0/protocols.rst index 29b74474ff1..814efcc84df 100644 --- a/docs/en/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/en/migration-guides/release-6.x/6.0/protocols.rst @@ -107,7 +107,7 @@ The new API requires you to create the :cpp:type:`esp_tls_t` structure using :cp Unified Private Key Interface ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The ``use_secure_element`` field has been removed from :cpp:type:`esp_tls_cfg`, :cpp:type:`esp_tls_cfg_server`, and :cpp:type:`httpd_ssl_config`. The ATECC608A secure element and all other hardware-backed key sources (DS peripheral, ECDSA peripheral, Key Manager) are now accessed through a unified :cpp:type:`esp_key_config_t` interface via PSA Crypto key IDs. +The ``use_secure_element`` field in :cpp:type:`esp_tls_cfg`, :cpp:type:`esp_tls_cfg_server`, and :cpp:type:`httpd_ssl_config` is deprecated and no longer functional: setting it to ``true`` makes the connection (or server start) fail with ``ESP_ERR_NOT_SUPPORTED``. The field is kept only for source compatibility and will be removed in the next major release. The ATECC608A secure element and all other hardware-backed key sources (DS peripheral, ECDSA peripheral, Key Manager) are now accessed through a unified :cpp:type:`esp_key_config_t` interface via PSA Crypto key IDs. **Migration Steps** @@ -115,7 +115,7 @@ The ``use_secure_element`` field has been removed from :cpp:type:`esp_tls_cfg`, 2. The ``atcab_init()`` call is no longer performed internally by ESP-TLS. Applications using the ATECC608A must ensure the secure element is initialized at the application level before use. Refer to the `esp-cryptoauthlib documentation `_ for details. -3. The ``esp_transport_ssl_use_secure_element()`` function has been removed from ``tcp_transport``. Use ``esp_transport_ssl_set_client_key_config()`` instead. +3. The ``esp_transport_ssl_use_secure_element()`` function in ``tcp_transport`` is deprecated and no longer functional (the connection will fail with ``ESP_ERR_NOT_SUPPORTED``). Use ``esp_transport_ssl_set_client_key_config()`` instead. 4. The Kconfig options for the secure element driver have been consolidated from ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN`` / ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY`` into a single ``CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED``. The old names are automatically mapped via ``sdkconfig.rename``. diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst index f1eb34a1795..4f8e6fa9a6a 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/protocols.rst @@ -107,7 +107,7 @@ ESP-TLS 已移除内置的 wolfSSL TLS 协议栈支持。使用 wolfSSL 的用 统一私钥接口 ~~~~~~~~~~~~~ -:cpp:type:`esp_tls_cfg`、:cpp:type:`esp_tls_cfg_server` 和 :cpp:type:`httpd_ssl_config` 中的 ``use_secure_element`` 字段已被移除。ATECC608A 安全元件和所有其他硬件支持的密钥源(DS 外设、ECDSA 外设、密钥管理器)现在通过统一的 :cpp:type:`esp_key_config_t` 接口和 PSA Crypto 密钥 ID 来访问。 +:cpp:type:`esp_tls_cfg`、:cpp:type:`esp_tls_cfg_server` 和 :cpp:type:`httpd_ssl_config` 中的 ``use_secure_element`` 字段已被弃用且不再起作用:将其设置为 ``true`` 会使连接(或服务器启动)失败并返回 ``ESP_ERR_NOT_SUPPORTED``。保留该字段仅是为了源代码兼容性,它将在下一个主版本中被移除。ATECC608A 安全元件和所有其他硬件支持的密钥源(DS 外设、ECDSA 外设、密钥管理器)现在通过统一的 :cpp:type:`esp_key_config_t` 接口和 PSA Crypto 密钥 ID 来访问。 **迁移步骤** @@ -115,7 +115,7 @@ ESP-TLS 已移除内置的 wolfSSL TLS 协议栈支持。使用 wolfSSL 的用 2. ``atcab_init()`` 调用不再由 ESP-TLS 内部执行。使用 ATECC608A 的应用程序必须确保在使用前在应用层初始化安全元件。详情请参阅 `esp-cryptoauthlib 文档 `_。 -3. ``esp_transport_ssl_use_secure_element()`` 函数已从 ``tcp_transport`` 中移除。请改用 ``esp_transport_ssl_set_client_key_config()``。 +3. ``tcp_transport`` 中的 ``esp_transport_ssl_use_secure_element()`` 函数已被弃用且不再起作用(连接将失败并返回 ``ESP_ERR_NOT_SUPPORTED``)。请改用 ``esp_transport_ssl_set_client_key_config()``。 4. 安全元件驱动的 Kconfig 选项已从 ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN`` / ``CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY`` 合并为 ``CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED``。旧名称通过 ``sdkconfig.rename`` 自动映射。