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..5f84f10813b 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,10 @@ 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. + 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 clientkey_pem_buf @@ -184,8 +189,12 @@ 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 */ + 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 @@ -315,6 +324,10 @@ 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. + 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 serverkey_pem_buf */ @@ -334,8 +347,12 @@ 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 */ + 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 diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index c8f7730517a..e7ebe3a747e 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" @@ -493,27 +483,32 @@ 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. */ -#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_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); + 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); 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 +752,62 @@ 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) { -#ifdef CONFIG_ESP_TLS_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 = { .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) { + 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); + 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); + 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; + } + 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 @@ -1005,26 +1034,61 @@ 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) { -#ifdef CONFIG_ESP_TLS_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 = { .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) { + 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); + 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); + 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; + } + 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) { @@ -1286,92 +1350,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-tls/hints.yml b/components/esp-tls/hints.yml index 6cf22e110ec..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 CONFIG_ESP_TLS_USE_SECURE_ELEMENT option, please 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/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. */ 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 32f5a15e2e9..9299a27167a 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -953,12 +953,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); @@ -977,26 +971,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 925336bf267..290786bc1cb 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..2c92b6c2dd6 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,7 +132,10 @@ struct httpd_ssl_config { /** Enable tls session tickets */ bool session_tickets; - /** Enable secure element for server session */ + /** @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 */ @@ -219,6 +225,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, \ @@ -227,7 +234,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 24ab03ec418..16af012c2cb 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -352,48 +352,56 @@ 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) { -#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; -#if SOC_ECDSA_SUPPORT_CURVE_P384 - (*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; -#else - 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); + /* 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 (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"); - } + 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; +#if SOC_ECDSA_SUPPORT_CURVE_P384 + (*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; #else - ESP_LOGE(TAG, "No Server key supplied"); + 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->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; + } + } 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; -#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/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index aa308bd90ad..209313ff087 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -481,6 +481,12 @@ 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") +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") @@ -549,11 +555,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 fc13f5e37b6..f97f2c1bcb4 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -1032,49 +1032,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 @@ -1542,19 +1542,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..596a30faddb 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -267,12 +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 +#ifdef CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED +#define SECURE_ELEMENT_DRIVER_ENABLED #endif #ifdef CONFIG_MBEDTLS_HARDWARE_ECC 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..665cc56855c --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_secure_element.h @@ -0,0 +1,241 @@ +/* + * 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. Only the first + * call succeeds; subsequent calls return PSA_ERROR_BAD_STATE. + * + * @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 + */ +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..da7e236b022 --- /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..91456dfd443 --- /dev/null +++ b/components/mbedtls/port/psa_driver/secure_element/psa_crypto_driver_secure_element.c @@ -0,0 +1,510 @@ +/* + * 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 "sdkconfig.h" + +#ifdef CONFIG_MBEDTLS_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). + * 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) +{ + 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; + } + + 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; +} + +/** + * @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_ptr; +} + +/** + * @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; + } + /* 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; + } + + /* 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); + memcpy(&operation->opaque_key, key_buffer, sizeof(secure_element_opaque_key_t)); + 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; + } + + 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, sig_len); + *signature_length = sig_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; + } + + /* 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 */ + 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 /* CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED */ diff --git a/components/mbedtls/sdkconfig.rename b/components/mbedtls/sdkconfig.rename new file mode 100644 index 00000000000..704feb32cac --- /dev/null +++ b/components/mbedtls/sdkconfig.rename @@ -0,0 +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 diff --git a/components/tcp_transport/include/esp_transport_ssl.h b/components/tcp_transport/include/esp_transport_ssl.h index 4dcd5c1338a..546679299ee 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 */ @@ -209,7 +209,10 @@ void esp_transport_ssl_set_ciphersuites_list(esp_transport_handle_t t, const int /** * @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 + * @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 */ @@ -223,6 +226,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..f3059d275c6 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -502,13 +502,13 @@ 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 +/* 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; } -#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 +575,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/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst index abcd1acd763..b3e157b60e0 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_http_client_config_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 8f5f5b13b7c..6b5500f0629 100644 --- a/docs/en/api-reference/protocols/esp_tls.rst +++ b/docs/en/api-reference/protocols/esp_tls.rst @@ -204,26 +204,28 @@ 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 -------------------------------------------------- -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 +233,45 @@ 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_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 = { + .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/en/migration-guides/release-6.x/6.0/protocols.rst b/docs/en/migration-guides/release-6.x/6.0/protocols.rst index 8495cc57ff0..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 @@ -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 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** + +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 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``. + +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..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,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_http_client_config_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 5db5fe2be4f..1967aed1cae 100644 --- a/docs/zh_CN/api-reference/protocols/esp_tls.rst +++ b/docs/zh_CN/api-reference/protocols/esp_tls.rst @@ -204,10 +204,12 @@ 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(安全元件) ----------------------------------------- -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 +217,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 +233,44 @@ 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_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 = { + .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 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..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 @@ -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`` 字段已被弃用且不再起作用:将其设置为 ``true`` 会使连接(或服务器启动)失败并返回 ``ESP_ERR_NOT_SUPPORTED``。保留该字段仅是为了源代码兼容性,它将在下一个主版本中被移除。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. ``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`` 自动映射。 + +详细使用示例请参阅 :ref:`atecc608a-with-esp-tls`。 + ESP HTTP 服务器 --------------- 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..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 @@ -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, + } + }; + 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(); #endif diff --git a/examples/protocols/https_server/simple/main/main.c b/examples/protocols/https_server/simple/main/main.c index 30878614d17..0ae2613138f 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, + } + }; + server_key.buffer.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..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 @@ -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, + } + }; + server_key.buffer.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) diff --git a/tools/test_idf_py/error_output.yml b/tools/test_idf_py/error_output.yml index 3cc548d0be3..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 CONFIG_ESP_TLS_USE_SECURE_ELEMENT option, please 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".'