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.
This commit is contained in:
Aditya Patwardhan
2026-06-25 11:31:37 +05:30
parent d51e467e7c
commit 36090b7161
17 changed files with 270 additions and 236 deletions
+4 -6
View File
@@ -22,7 +22,10 @@ endif()
idf_component_register(SRCS "${srcs}" idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto
PRIV_INCLUDE_DIRS "private_include" 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}) PRIV_REQUIRES ${priv_req})
idf_define_esp_err_codes(HEADERS esp_tls_errors.h) idf_define_esp_err_codes(HEADERS esp_tls_errors.h)
@@ -35,8 +38,3 @@ else()
target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_TLS_WITH_LWIP=1) target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_TLS_WITH_LWIP=1)
endif() endif()
endif() endif()
if(CONFIG_ESP_TLS_USE_SECURE_ELEMENT)
idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib)
endif()
-10
View File
@@ -22,16 +22,6 @@ menu "ESP-TLS"
esp_tls_stack_ops_t interface. esp_tls_stack_ops_t interface.
endchoice 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 config ESP_TLS_USE_DS_PERIPHERAL
bool "Use Digital Signature (DS) Peripheral with ESP-TLS" bool "Use Digital Signature (DS) Peripheral with ESP-TLS"
depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED depends on ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED
+5 -6
View File
@@ -9,6 +9,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "esp_err.h" #include "esp_err.h"
#include "esp_tls_errors.h" #include "esp_tls_errors.h"
#include "esp_key_config.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#ifdef CONFIG_ESP_TLS_USING_MBEDTLS #ifdef CONFIG_ESP_TLS_USING_MBEDTLS
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
@@ -160,6 +161,8 @@ typedef struct esp_tls_cfg {
const unsigned char *clientkey_pem_buf; /*!< Client key legacy name */ 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 { union {
unsigned int clientkey_bytes; /*!< Size of client key pointed to by unsigned int clientkey_bytes; /*!< Size of client key pointed to by
clientkey_pem_buf clientkey_pem_buf
@@ -184,9 +187,6 @@ typedef struct esp_tls_cfg {
underneath socket will be configured in non underneath socket will be configured in non
blocking mode after tls session is established */ 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. int timeout_ms; /*!< Network timeout in milliseconds.
Note: If this value is not set, by default the timeout is Note: If this value is not set, by default the timeout is
set to 10 seconds. If you wish that the session should wait 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 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 { union {
unsigned int serverkey_bytes; /*!< Size of server key pointed to by unsigned int serverkey_bytes; /*!< Size of server key pointed to by
serverkey_pem_buf */ 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) */ 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. uint32_t tls_handshake_timeout_ms; /*!< TLS handshake timeout in milliseconds.
Note: If this value is not set, by default the timeout is Note: If this value is not set, by default the timeout is
set to 10 seconds. If you wish that the session should wait set to 10 seconds. If you wish that the session should wait
+75 -126
View File
@@ -32,16 +32,6 @@
#include "esp_crt_bundle.h" #include "esp_crt_bundle.h"
#endif #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) #if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
#include <pk_wrap.h> #include <pk_wrap.h>
#include "psa/crypto.h" #include "psa/crypto.h"
@@ -486,6 +476,7 @@ void esp_mbedtls_cleanup(esp_tls_t *tls)
if (!tls) { if (!tls) {
return; return;
} }
if (tls->cacert_ptr != global_cacert) { if (tls->cacert_ptr != global_cacert) {
mbedtls_x509_crt_free(tls->cacert_ptr); 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_pk_free(&tls->clientkey);
mbedtls_ssl_config_free(&tls->conf); mbedtls_ssl_config_free(&tls->conf);
mbedtls_ssl_free(&tls->ssl); 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) static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len)
@@ -757,27 +745,50 @@ 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 #endif // CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL
} }
if (cfg->use_secure_element) { if (cfg->server_key != NULL && cfg->server_key->source == ESP_KEY_SOURCE_BUFFER) {
#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT /* Unified key config with buffer source */
esp_tls_pki_t pki = { esp_tls_pki_t pki = {
.public_cert = &tls->servercert, .public_cert = &tls->servercert,
.pk_key = &tls->serverkey, .pk_key = &tls->serverkey,
.publiccert_pem_buf = cfg->servercert_buf, .publiccert_pem_buf = cfg->servercert_buf,
.publiccert_pem_bytes = cfg->servercert_bytes, .publiccert_pem_bytes = cfg->servercert_bytes,
.privkey_pem_buf = NULL, .privkey_pem_buf = cfg->server_key->buffer.data,
.privkey_pem_bytes = 0, .privkey_pem_bytes = cfg->server_key->buffer.len,
.privkey_password = NULL, .privkey_password = (const unsigned char *)cfg->server_key->buffer.password,
.privkey_password_len = 0, .privkey_password_len = cfg->server_key->buffer.password_len,
}; };
esp_ret = set_pki_context(tls, &pki);
ret = esp_set_atecc608a_pki_context(tls, (void*) &pki); if (esp_ret != ESP_OK) {
if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set server pki context");
return ret; return esp_ret;
}
} 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
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->use_ecdsa_peripheral) {
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral; tls->use_ecdsa_peripheral = cfg->use_ecdsa_peripheral;
@@ -997,26 +1008,50 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t
#endif #endif
} }
if (cfg->use_secure_element) { if (cfg->client_key != NULL && cfg->client_key->source == ESP_KEY_SOURCE_BUFFER) {
#ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT /* Unified key config with buffer source */
esp_tls_pki_t pki = { esp_tls_pki_t pki = {
.public_cert = &tls->clientcert, .public_cert = &tls->clientcert,
.pk_key = &tls->clientkey, .pk_key = &tls->clientkey,
.publiccert_pem_buf = cfg->clientcert_buf, .publiccert_pem_buf = cfg->clientcert_buf,
.publiccert_pem_bytes = cfg->clientcert_bytes, .publiccert_pem_bytes = cfg->clientcert_bytes,
.privkey_pem_buf = NULL, .privkey_pem_buf = cfg->client_key->buffer.data,
.privkey_pem_bytes = 0, .privkey_pem_bytes = cfg->client_key->buffer.len,
.privkey_password = NULL, .privkey_password = (const unsigned char *)cfg->client_key->buffer.password,
.privkey_password_len = 0, .privkey_password_len = cfg->client_key->buffer.password_len,
}; };
ret = esp_set_atecc608a_pki_context(tls, (void*) &pki); esp_err_t esp_ret = set_pki_context(tls, &pki);
if (ret != ESP_OK) { if (esp_ret != ESP_OK) {
return ret; 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) { } else if (cfg->ds_data != NULL) {
#ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
if (cfg->clientcert_pem_buf == NULL) { if (cfg->clientcert_pem_buf == NULL) {
@@ -1278,92 +1313,6 @@ const int *esp_mbedtls_get_ciphersuites_list(void)
return mbedtls_ssl_list_ciphersuites(); 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 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
/* /*
* tf-psa-crypto 1.1 made mbedtls_pk_wrap_psa() call psa_export_public_key() on * tf-psa-crypto 1.1 made mbedtls_pk_wrap_psa() call psa_export_public_key() on
+2 -2
View File
@@ -1,7 +1,7 @@
if(NOT ${IDF_TARGET} STREQUAL "linux") if(NOT ${IDF_TARGET} STREQUAL "linux")
set(req lwip esp_event) set(req lwip esp_event esp_security)
else() else()
set(req linux esp_event) set(req linux esp_event esp_security)
endif() endif()
idf_component_register(SRCS "esp_http_client.c" idf_component_register(SRCS "esp_http_client.c"
+6 -6
View File
@@ -938,12 +938,6 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
} }
#endif #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_ESP_TLS_USE_DS_PERIPHERAL
if (config->ds_data != NULL) { if (config->ds_data != NULL) {
esp_transport_ssl_set_ds_data(ssl, config->ds_data); esp_transport_ssl_set_ds_data(ssl, config->ds_data);
@@ -962,6 +956,11 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
} }
#endif #endif
/* 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_pem) {
if (!config->client_key_len) { if (!config->client_key_len) {
esp_transport_ssl_set_client_key_data(ssl, config->client_key_pem, strlen(config->client_key_pem)); esp_transport_ssl_set_client_key_data(ssl, config->client_key_pem, strlen(config->client_key_pem));
@@ -983,6 +982,7 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
if (config->client_key_password && config->client_key_password_len > 0) { 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); esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len);
} }
}
if (config->skip_cert_common_name_check) { if (config->skip_cert_common_name_check) {
esp_transport_ssl_skip_common_name_check(ssl); esp_transport_ssl_skip_common_name_check(ssl);
@@ -10,6 +10,7 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_key_config.h"
#include <sys/socket.h> #include <sys/socket.h>
#ifdef __cplusplus #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. */ 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 */ 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 */ 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 */ 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 */ 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) */ 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 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 */ name. For the most common cases the following is ok: const char **alpn_protos = { "h2", NULL }; - where 'h2' is the protocol name */
#endif #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 #if CONFIG_ESP_TLS_USE_DS_PERIPHERAL
void *ds_data; /*!< Pointer for digital signature peripheral context, see ESP-TLS Documentation for more details */ void *ds_data; /*!< Pointer for digital signature peripheral context, see ESP-TLS Documentation for more details */
#endif #endif
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -105,6 +105,9 @@ struct httpd_ssl_config {
/** Private key byte length */ /** Private key byte length */
size_t prvtkey_len; 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 */ /** Use ECDSA peripheral to use private key */
bool use_ecdsa_peripheral; bool use_ecdsa_peripheral;
@@ -129,9 +132,6 @@ struct httpd_ssl_config {
/** Enable tls session tickets */ /** Enable tls session tickets */
bool session_tickets; bool session_tickets;
/** Enable secure element for server session */
bool use_secure_element;
/** User callback for esp_https_server */ /** User callback for esp_https_server */
esp_https_server_user_cb *user_cb; esp_https_server_user_cb *user_cb;
@@ -227,7 +227,6 @@ typedef struct httpd_ssl_config httpd_ssl_config_t;
.port_secure = 443, \ .port_secure = 443, \
.port_insecure = 80, \ .port_insecure = 80, \
.session_tickets = false, \ .session_tickets = false, \
.use_secure_element = false, \
.user_cb = NULL, \ .user_cb = NULL, \
.ssl_userdata = NULL, \ .ssl_userdata = NULL, \
.cert_select_cb = NULL, \ .cert_select_cb = NULL, \
@@ -348,9 +348,6 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht
#endif #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 #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
(*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral; (*ssl_ctx)->tls_cfg->use_ecdsa_peripheral = config->use_ecdsa_peripheral;
@@ -364,6 +361,9 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht
ret = ESP_ERR_NOT_SUPPORTED; ret = ESP_ERR_NOT_SUPPORTED;
goto exit; goto exit;
#endif #endif
} 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) { } else if (config->prvtkey_pem != NULL && config->prvtkey_len > 0) {
cfg->serverkey_buf = malloc(config->prvtkey_len); cfg->serverkey_buf = malloc(config->prvtkey_len);
@@ -390,7 +390,6 @@ static esp_err_t create_secure_context(const struct httpd_ssl_config *config, ht
goto exit; goto exit;
#endif #endif
} }
}
return ret; return ret;
+3 -1
View File
@@ -2,7 +2,9 @@ idf_build_get_property(target IDF_TARGET)
idf_build_get_property(non_os_build NON_OS_BUILD) idf_build_get_property(non_os_build NON_OS_BUILD)
if(${target} STREQUAL "linux") 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() endif()
set(srcs "") set(srcs "")
@@ -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
@@ -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 * 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); 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) * @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); 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. * @brief Set PSK key and hint for PSK server/client verification in esp-tls component.
* Important notes: * Important notes:
+6 -8
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; 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 #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))) 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 #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) 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); GET_SSL_FROM_TRANSPORT_OR_RETURN(ssl, t);
@@ -20,6 +20,7 @@
#include <esp_log.h> #include <esp_log.h>
#include <esp_timer.h> #include <esp_timer.h>
#include <esp_local_ctrl.h> #include <esp_local_ctrl.h>
#include <esp_key_config.h>
#include <protocomm_ble.h> #include <protocomm_ble.h>
static const char *TAG = "control"; static const char *TAG = "control";
@@ -239,8 +240,14 @@ void start_esp_local_ctrl_service(void)
/* Load server private key */ /* Load server private key */
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
https_conf.prvtkey_pem = prvtkey_pem_start; static esp_key_config_t server_key = {
https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; .source = ESP_KEY_SOURCE_BUFFER,
.buffer = {
.data = prvtkey_pem_start,
.len = prvtkey_pem_end - prvtkey_pem_start,
}
};
https_conf.server_key = &server_key;
#else #else
httpd_config_t http_conf = HTTPD_DEFAULT_CONFIG(); httpd_config_t http_conf = HTTPD_DEFAULT_CONFIG();
#endif #endif
@@ -25,6 +25,7 @@
#include <esp_https_server.h> #include <esp_https_server.h>
#include "esp_tls.h" #include "esp_tls.h"
#include "esp_key_config.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_EXAMPLE_ENABLE_HTTPS_SERVER_CUSTOM_CIPHERSUITES #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_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
conf.prvtkey_pem = prvtkey_pem_start; static esp_key_config_t server_key = {
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; .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 #if CONFIG_EXAMPLE_ENABLE_HTTPS_SERVER_CUSTOM_CIPHERSUITES
static const int ciphersuites_to_use[] = { static const int ciphersuites_to_use[] = {
@@ -22,6 +22,7 @@
#include <unistd.h> #include <unistd.h>
#endif // !CONFIG_IDF_TARGET_LINUX #endif // !CONFIG_IDF_TARGET_LINUX
#include <esp_https_server.h> #include <esp_https_server.h>
#include "esp_key_config.h"
#include "keep_alive.h" #include "keep_alive.h"
#include "sdkconfig.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_start[] asm("_binary_prvtkey_pem_start");
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
conf.prvtkey_pem = prvtkey_pem_start; static esp_key_config_t server_key = {
conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start; .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); esp_err_t ret = httpd_ssl_start(&server, &conf);
if (ESP_OK != ret) { if (ESP_OK != ret) {
+1 -1
View File
@@ -8,6 +8,6 @@ idf_component_mock(INCLUDE_DIRS "${original_esp_tls_dir}"
"${original_esp_tls_dir}/esp-tls-crypto" "${original_esp_tls_dir}/esp-tls-crypto"
MOCK_HEADER_FILES ${original_esp_tls_dir}/esp_tls.h MOCK_HEADER_FILES ${original_esp_tls_dir}/esp_tls.h
${original_esp_tls_dir}/esp-tls-crypto/esp_tls_crypto.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) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-array-parameter)