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 36090b7161)
This commit is contained in:
Aditya Patwardhan
2026-04-08 18:37:10 +05:30
parent c9bdb79314
commit 2325a727d8
17 changed files with 270 additions and 236 deletions

View File

@@ -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()

View File

@@ -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

View File

@@ -9,6 +9,7 @@
#include <stdbool.h>
#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

View File

@@ -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 <pk_wrap.h>
#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

View File

@@ -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"

View File

@@ -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) {

View File

@@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_key_config.h"
#include <sys/socket.h>
#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

View File

@@ -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, \

View File

@@ -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;

View File

@@ -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 "")

View File

@@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#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

View File

@@ -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:

View File

@@ -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);

View File

@@ -20,6 +20,7 @@
#include <esp_log.h>
#include <esp_timer.h>
#include <esp_local_ctrl.h>
#include <esp_key_config.h>
#include <protocomm_ble.h>
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

View File

@@ -25,6 +25,7 @@
#include <esp_https_server.h>
#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[] = {

View File

@@ -22,6 +22,7 @@
#include <unistd.h>
#endif // !CONFIG_IDF_TARGET_LINUX
#include <esp_https_server.h>
#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) {

View File

@@ -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)