From 89f555d6985a3189ab7ba406f99f1f4eacc0e503 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 31 Dec 2025 12:00:41 +0530 Subject: [PATCH] feat(esp_tee): Migrate TEE attestation to the PSA interface --- components/esp_tee/CMakeLists.txt | 4 +- components/esp_tee/Kconfig.projbuild | 9 +++ .../scripts/esp32c5/sec_srv_tbl_default.yml | 10 ++- .../scripts/esp32c6/sec_srv_tbl_default.yml | 10 ++- .../scripts/esp32c61/sec_srv_tbl_default.yml | 10 ++- .../scripts/esp32h2/sec_srv_tbl_default.yml | 10 ++- .../esp_tee/src/esp_secure_service_wrapper.c | 81 +++++-------------- components/esp_tee/subproject/CMakeLists.txt | 2 +- .../attestation/esp_att_utils_json.c | 25 +++++- .../components/attestation/esp_attestation.c | 46 +++++++++-- .../attestation/include/esp_attestation.h | 28 +++++-- .../private_include/esp_attestation_utils.h | 17 +++- .../components/tee_attestation/CMakeLists.txt | 17 ---- .../tee_attestation/esp_tee_attestation.c | 55 ------------- .../tee_attestation/esp_tee_attestation.h | 42 ---------- .../main/core/esp_secure_services.c | 53 +++++++++++- components/mbedtls/CMakeLists.txt | 6 +- .../mbedtls/esp_tee/esp_tee_mbedtls.cmake | 3 + .../include/psa/error.h | 0 .../port/include/psa/initial_attestation.h | 71 ++++++++++++++++ .../include/psa/internal_trusted_storage.h | 0 .../psa_attestation/psa_initial_attestation.c | 36 +++++++++ 22 files changed, 323 insertions(+), 212 deletions(-) delete mode 100644 components/esp_tee/subproject/components/tee_attestation/CMakeLists.txt delete mode 100644 components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.c delete mode 100644 components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.h rename components/mbedtls/port/{psa_crypto_storage => }/include/psa/error.h (100%) create mode 100644 components/mbedtls/port/include/psa/initial_attestation.h rename components/mbedtls/port/{psa_crypto_storage => }/include/psa/internal_trusted_storage.h (100%) create mode 100644 components/mbedtls/port/psa_attestation/psa_initial_attestation.c diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index f5f7ec1da4..f75bb4b970 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -80,8 +80,8 @@ else() idf_component_register(INCLUDE_DIRS include SRCS ${srcs} - PRIV_REQUIRES efuse esp_security esp_system esp_stdio spi_flash esptool_py esp_hal_wdt) - + PRIV_REQUIRES efuse esp_hal_wdt esp_security esp_stdio + esp_system esptool_py mbedtls spi_flash) if(CONFIG_SECURE_ENABLE_TEE) set(EXTRA_LINK_FLAGS) list(APPEND EXTRA_LINK_FLAGS "-u esp_tee_app_config") diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index 6cb5be8eb8..acd39cf640 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -127,6 +127,15 @@ menu "ESP-TEE (Trusted Execution Environment)" storing the ECDSA keypair for executing sign/verify operations from the TEE side for attestation. + config SECURE_TEE_ATT_PSA_CERT_REF + depends on SECURE_TEE_ATTESTATION + string + default "0632793520245-10010" if IDF_TARGET_ESP32C6 + default "0632793520351-10100" if IDF_TARGET_ESP32H2 + default "XXXXXXXXXXXXX-XXXXX" + help + PSA certification ID string for the attestation token + endmenu config SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 diff --git a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml index eca5272850..473b16e2c2 100644 --- a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml @@ -305,9 +305,13 @@ secure_services: - family: attestation entries: - id: 170 - type: custom - function: esp_tee_att_generate_token - args: 6 + type: IDF + function: psa_initial_attest_get_token + args: 5 + - id: 171 + type: IDF + function: psa_initial_attest_get_token_size + args: 2 # ID: 175-194 (20) - Secure Storage - family: secure_storage entries: diff --git a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml index c0a2c52c80..4890d1e5e8 100644 --- a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml @@ -245,9 +245,13 @@ secure_services: - family: attestation entries: - id: 170 - type: custom - function: esp_tee_att_generate_token - args: 6 + type: IDF + function: psa_initial_attest_get_token + args: 5 + - id: 171 + type: IDF + function: psa_initial_attest_get_token_size + args: 2 # ID: 175-194 (20) - Secure Storage - family: secure_storage entries: diff --git a/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml index ded5928aac..f334bb360d 100644 --- a/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml @@ -210,9 +210,13 @@ secure_services: - family: attestation entries: - id: 170 - type: custom - function: esp_tee_att_generate_token - args: 6 + type: IDF + function: psa_initial_attest_get_token + args: 5 + - id: 171 + type: IDF + function: psa_initial_attest_get_token_size + args: 2 # ID: 175-194 (20) - Secure Storage - family: secure_storage entries: diff --git a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml index 80f94feee4..b6a775b878 100644 --- a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml @@ -249,9 +249,13 @@ secure_services: - family: attestation entries: - id: 170 - type: custom - function: esp_tee_att_generate_token - args: 6 + type: IDF + function: psa_initial_attest_get_token + args: 5 + - id: 171 + type: IDF + function: psa_initial_attest_get_token_size + args: 2 # ID: 175-194 (20) - Secure Storage - family: secure_storage entries: diff --git a/components/esp_tee/src/esp_secure_service_wrapper.c b/components/esp_tee/src/esp_secure_service_wrapper.c index 4be9c3ffc8..d5abd001ec 100644 --- a/components/esp_tee/src/esp_secure_service_wrapper.c +++ b/components/esp_tee/src/esp_secure_service_wrapper.c @@ -14,9 +14,15 @@ #include "hal/spi_flash_hal.h" #include "hal/spi_flash_types.h" #include "esp_private/mspi_timing_tuning.h" +#if SOC_AES_SUPPORTED +#include "aes/esp_aes.h" +#endif #if SOC_SHA_SUPPORTED #include "hal/sha_types.h" -#include "hal/sha_hal.h" +#include "psa_crypto_driver_esp_sha_contexts.h" +#endif +#if SOC_ECC_SUPPORTED +#include "ecc_impl.h" #endif #if SOC_HMAC_SUPPORTED #include "esp_hmac.h" @@ -25,6 +31,7 @@ #include "esp_ds.h" #include "rom/digital_signature.h" #endif +#include "psa/crypto.h" #include "esp_crypto_lock.h" #include "esp_flash.h" @@ -61,12 +68,6 @@ void IRAM_ATTR __wrap_wdt_hal_deinit(wdt_hal_context_t *hal) /* ---------------------------------------------- AES ------------------------------------------------- */ #if SOC_AES_SUPPORTED -typedef struct { - uint8_t key_bytes; - volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ - uint8_t key[32]; -} esp_aes_context; - int __wrap_esp_aes_intr_alloc(void) { return esp_tee_service_call(1, SS_ESP_AES_INTR_ALLOC); @@ -158,49 +159,6 @@ int __wrap_esp_aes_crypt_ofb(esp_aes_context *ctx, /* ---------------------------------------------- SHA ------------------------------------------------- */ #if SOC_SHA_SUPPORTED -typedef enum { - ESP_SHA1_STATE_INIT, - ESP_SHA1_STATE_IN_PROCESS -} esp_sha1_state; - -typedef enum { - ESP_SHA256_STATE_INIT, - ESP_SHA256_STATE_IN_PROCESS -} esp_sha256_state; - -typedef enum { - ESP_SHA512_STATE_INIT, - ESP_SHA512_STATE_IN_PROCESS -} esp_sha512_state; - -typedef struct { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - int first_block; /*!< if first then true else false */ - esp_sha_type mode; - esp_sha1_state sha_state; -} esp_sha1_context; - -typedef struct { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - int first_block; /*!< if first then true, else false */ - esp_sha_type mode; - esp_sha256_state sha_state; -} esp_sha256_context; - -typedef struct { - uint64_t total[2]; /*!< number of bytes processed */ - uint64_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[128]; /*!< data block being processed */ - int first_block; - esp_sha_type mode; - uint32_t t_val; /*!< t_val for 512/t mode */ - esp_sha512_state sha_state; -} esp_sha512_context; - void __wrap_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) { esp_tee_service_call(5, SS_ESP_SHA, @@ -343,15 +301,6 @@ void __wrap_esp_crypto_mpi_enable_periph_clk(bool enable) /* ---------------------------------------------- ECC ------------------------------------------------- */ #if SOC_ECC_SUPPORTED -#define P256_LEN (256/8) -#define P192_LEN (192/8) - -typedef struct { - uint8_t x[P256_LEN]; /* Little endian order */ - uint8_t y[P256_LEN]; /* Little endian order */ - unsigned len; /* P192_LEN or P256_LEN */ -} ecc_point_t; - int __wrap_esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_point_t *result, bool verify_first) { esp_crypto_ecc_lock_acquire(); @@ -541,3 +490,17 @@ void IRAM_ATTR __wrap_spi_timing_get_flash_timing_param(spi_flash_hal_timing_con } #endif #endif + +#if CONFIG_SECURE_TEE_ATTESTATION +psa_status_t __wrap_psa_initial_attest_get_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size) +{ + return (esp_err_t)esp_tee_service_call_with_noniram_intr_disabled(6, SS_PSA_INITIAL_ATTEST_GET_TOKEN, auth_challenge, challenge_size, + token_buf, token_buf_size, token_size); +} + +psa_status_t __wrap_psa_initial_attest_get_token_size(size_t challenge_size, size_t *token_size) +{ + return (esp_err_t)esp_tee_service_call_with_noniram_intr_disabled(3, SS_PSA_INITIAL_ATTEST_GET_TOKEN_SIZE, challenge_size, token_size); +} +#endif diff --git a/components/esp_tee/subproject/CMakeLists.txt b/components/esp_tee/subproject/CMakeLists.txt index 4c3716077f..693219c654 100644 --- a/components/esp_tee/subproject/CMakeLists.txt +++ b/components/esp_tee/subproject/CMakeLists.txt @@ -28,7 +28,7 @@ set(NON_OS_BUILD 1) list(APPEND COMPONENTS bootloader_support efuse esp_hal_mspi esp_hal_wdt esp_security mbedtls esp_stdio) # TEE-specific components -list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage tee_attestation) +list(APPEND COMPONENTS attestation tee_flash_mgr tee_ota_ops tee_sec_storage) include_directories("${SECURE_SERVICE_HEADERS_DIR}") diff --git a/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c b/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c index c8f238b12e..c0810ff45f 100644 --- a/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c +++ b/components/esp_tee/subproject/components/attestation/esp_att_utils_json.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -155,13 +155,31 @@ esp_err_t esp_att_utils_eat_data_to_json(struct esp_att_sw_claim_list *head, con esp_att_sw_claim_list_t *claim = NULL; char *claim_json = NULL; - json_gen_obj_set_int(&json_gen, "nonce", cfg->nonce); + // Convert auth_challenge to hex string - allocate based on actual challenge size + size_t auth_challenge_hexstr_size = cfg->challenge_size * 2 + 1; + char *auth_challenge_hexstr = calloc(auth_challenge_hexstr_size, sizeof(char)); + if (auth_challenge_hexstr == NULL) { + free(json_buf); + return ESP_ERR_NO_MEM; + } + + esp_err_t err = esp_att_utils_hexbuf_to_hexstr(cfg->auth_challenge, cfg->challenge_size, + auth_challenge_hexstr, auth_challenge_hexstr_size); + if (err != ESP_OK) { + free(auth_challenge_hexstr); + free(json_buf); + return err; + } + json_gen_obj_set_string(&json_gen, "auth_challenge", auth_challenge_hexstr); + free(auth_challenge_hexstr); + json_gen_obj_set_int(&json_gen, "client_id", cfg->client_id); json_gen_obj_set_int(&json_gen, "device_ver", cfg->device_ver); char dev_id_hexstr[ESP_ATT_EAT_DEV_ID_SZ * 2 + 1] = {0}; - esp_err_t err = esp_att_utils_hexbuf_to_hexstr(cfg->device_id, sizeof(cfg->device_id), dev_id_hexstr, sizeof(dev_id_hexstr)); + err = esp_att_utils_hexbuf_to_hexstr(cfg->device_id, sizeof(cfg->device_id), dev_id_hexstr, sizeof(dev_id_hexstr)); if (err != ESP_OK) { + free(json_buf); return err; } json_gen_obj_set_string(&json_gen, "device_id", dev_id_hexstr); @@ -170,6 +188,7 @@ esp_err_t esp_att_utils_eat_data_to_json(struct esp_att_sw_claim_list *head, con char inst_id_hexstr[DIGEST_HEXSTR_LEN] = {0}; err = esp_att_utils_hexbuf_to_hexstr(cfg->instance_id, sizeof(cfg->instance_id), inst_id_hexstr, sizeof(inst_id_hexstr)); if (err != ESP_OK) { + free(json_buf); return err; } json_gen_obj_set_string(&json_gen, "instance_id", inst_id_hexstr); diff --git a/components/esp_tee/subproject/components/attestation/esp_attestation.c b/components/esp_tee/subproject/components/attestation/esp_attestation.c index a62be9c367..c239e82681 100644 --- a/components/esp_tee/subproject/components/attestation/esp_attestation.c +++ b/components/esp_tee/subproject/components/attestation/esp_attestation.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -165,10 +165,17 @@ exit: return err; } -esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, - uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len) +esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size) { - if (token_buf == NULL || token_len == NULL || psa_cert_ref == NULL) { + if (auth_challenge == NULL || token_buf == NULL || token_buf_size == 0 || token_size == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 && + challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 && + challenge_size != PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) { + ESP_LOGE(TAG, "Invalid challenge size"); return ESP_ERR_INVALID_ARG; } @@ -191,10 +198,13 @@ esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id, } esp_att_token_cfg_t cfg = { - .nonce = nonce, - .client_id = client_id, + .auth_challenge = (uint8_t *)auth_challenge, + .challenge_size = challenge_size, + /* TODO: client_id should point to the API caller (REE or TEE) */ + .client_id = 0x0FACADE0, + /* TODO: PSA cert ref should be configurable or derived from system config */ + .psa_cert_ref = ESP_ATT_TK_PSA_CERT_REF, }; - memcpy(cfg.psa_cert_ref, psa_cert_ref, sizeof(cfg.psa_cert_ref)); err = populate_att_token_cfg(&cfg, &keypair); if (err != ESP_OK) { @@ -285,10 +295,30 @@ esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id, free(sign_json); json_gen_end_object(&jstr); - *token_len = json_gen_str_end(&jstr); + *token_size = json_gen_str_end(&jstr); err = ESP_OK; exit: free_sw_claim_list(); return err; } + +esp_err_t esp_att_get_token_size(size_t challenge_size, size_t *token_size) +{ + if (token_size == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (challenge_size) { + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32: + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48: + case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64: + *token_size = ESP_ATT_TK_MIN_SIZE; + break; + default: + *token_size = UINT32_MAX; + return ESP_ERR_INVALID_ARG; + } + + return ESP_OK; +} diff --git a/components/esp_tee/subproject/components/attestation/include/esp_attestation.h b/components/esp_tee/subproject/components/attestation/include/esp_attestation.h index d83725d0f5..385060341d 100644 --- a/components/esp_tee/subproject/components/attestation/include/esp_attestation.h +++ b/components/esp_tee/subproject/components/attestation/include/esp_attestation.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,17 +14,31 @@ extern "C" { /** * @brief Generate an entity attestation token * - * @param[in] nonce Nonce value to include in the token - * @param[in] client_id Client identifier to include in the token - * @param[in] psa_cert_ref PSA certificate reference to include in the token + * @param[in] auth_challenge Authentication challenge buffer + * @param[in] challenge_size Size of the authentication challenge * @param[in] token_buf Buffer to store the generated token * @param[in] token_buf_size Size of the token buffer - * @param[out] token_len Pointer to store the actual length of the generated token + * @param[out] token_size Pointer to store the actual length of the generated token * * @return esp_err_t ESP_OK on success, or an error code on failure */ -esp_err_t esp_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, - uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len); +esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size); + +/** + * @brief Get the required buffer size for an attestation token + * + * @param[in] challenge_size Size of the authentication challenge in bytes + * Must be one of: PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32), + * PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48), or + * PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64) + * @param[out] token_size Pointer to store the required token buffer size + * + * @return + * - `ESP_OK` on success + * - `ESP_ERR_INVALID_ARG` if token_size is NULL or challenge_size is invalid + */ +esp_err_t esp_att_get_token_size(size_t challenge_size, size_t *token_size); #ifdef __cplusplus } diff --git a/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h b/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h index e26f45ea88..50c90e5760 100644 --- a/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h +++ b/components/esp_tee/subproject/components/attestation/private_include/esp_attestation_utils.h @@ -12,8 +12,10 @@ #include "esp_app_desc.h" #include "esp_attestation.h" - #include "psa/crypto.h" +#include "psa/initial_attestation.h" + +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -42,11 +44,16 @@ extern "C" { #define ESP_ATT_SIGN_JSON_MAX_SZ (192) #define ESP_ATT_TK_MIN_SIZE (ESP_ATT_HDR_JSON_MAX_SZ + ESP_ATT_EAT_JSON_MAX_SZ + ESP_ATT_PUBKEY_JSON_MAX_SZ + ESP_ATT_SIGN_JSON_MAX_SZ) +#if ESP_ATT_TK_MIN_SIZE > PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE +#error "Attestation token size may exceed the bounds set by the PSA interface" +#endif #if ESP_TEE_BUILD && CONFIG_SECURE_TEE_ATTESTATION -#define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_STR_ID) +#define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_STR_ID) +#define ESP_ATT_TK_PSA_CERT_REF (CONFIG_SECURE_TEE_ATT_PSA_CERT_REF) #else -#define ESP_ATT_TK_KEY_ID ("NULL") +#define ESP_ATT_TK_KEY_ID ("NULL") +#define ESP_ATT_TK_PSA_CERT_REF ("NULL") #endif /** @@ -112,7 +119,8 @@ typedef struct { * @brief Structure to hold the Entity Attestation Token initial configuration */ typedef struct { - uint32_t nonce; /**< Nonce value */ + uint8_t *auth_challenge; /**< Authentication challenge */ + size_t challenge_size; /**< Challenge size */ uint32_t client_id; /**< Client identifier (Attestation relying party) */ uint32_t device_ver; /**< Device version */ uint8_t device_id[SHA256_DIGEST_SZ]; /**< Device identifier */ @@ -120,6 +128,7 @@ typedef struct { char psa_cert_ref[32]; /**< PSA certificate reference */ uint8_t device_stat; /**< Flags indicating device status */ } esp_att_token_cfg_t; + /** * @brief Structure to hold an ECDSA key pair */ diff --git a/components/esp_tee/subproject/components/tee_attestation/CMakeLists.txt b/components/esp_tee/subproject/components/tee_attestation/CMakeLists.txt deleted file mode 100644 index 02b16475e0..0000000000 --- a/components/esp_tee/subproject/components/tee_attestation/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -idf_build_get_property(esp_tee_build ESP_TEE_BUILD) - -set(srcs) -set(include_dirs ".") -set(priv_requires esp_tee) - -if(esp_tee_build) - list(APPEND priv_requires attestation main) -endif() - -if(CONFIG_SECURE_TEE_ATTESTATION) - list(APPEND srcs "esp_tee_attestation.c") -endif() - -idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ${include_dirs} - PRIV_REQUIRES ${priv_requires}) diff --git a/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.c b/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.c deleted file mode 100644 index 741e8d16c3..0000000000 --- a/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include - -#include "esp_log.h" -#include "esp_err.h" - -#if ESP_TEE_BUILD -#include "esp_fault.h" -#include "esp_tee_memory_utils.h" -#include "esp_attestation.h" -#endif - -#include "esp_tee.h" -#include "secure_service_num.h" - -#include "sdkconfig.h" - -static __attribute__((unused)) const char *TAG = "esp_tee_att"; - -#if ESP_TEE_BUILD - -esp_err_t _ss_esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, - uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len) -{ - bool valid_addr = (esp_tee_ptr_in_ree((void *)psa_cert_ref) && - esp_tee_ptr_in_ree((void *)token_buf) && - esp_tee_ptr_in_ree((void *)token_len)); - valid_addr &= (esp_tee_ptr_in_ree((void *)((char *)psa_cert_ref + 20)) && - esp_tee_ptr_in_ree((void *)((char *)token_buf + token_buf_size))); - - if (!valid_addr) { - return ESP_ERR_INVALID_ARG; - } - ESP_FAULT_ASSERT(valid_addr); - - return esp_att_generate_token(nonce, client_id, psa_cert_ref, token_buf, token_buf_size, token_len); -} - -#else - -esp_err_t esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, - uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len) -{ - return (esp_err_t)esp_tee_service_call_with_noniram_intr_disabled(7, SS_ESP_TEE_ATT_GENERATE_TOKEN, nonce, client_id, - psa_cert_ref, token_buf, token_buf_size, token_len); -} -#endif diff --git a/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.h b/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.h deleted file mode 100644 index 4de73aa69f..0000000000 --- a/components/esp_tee/subproject/components/tee_attestation/esp_tee_attestation.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Generate and return an entity attestation token (EAT) from the TEE - * - * The EAT consists of the below details: - * - For all firmware images (Bootloader, active TEE and non-secure app) - * - Project and ESP-IDF version - * - Digest (SHA256) - * - Public key corresponding to the private key used for signing (in compressed format) - * - Signature generated using the ECDSA key stored in the configured slot of the TEE's Secure Storage (`r` and `s` components) - * - * @param[in] nonce Attestation request identification - * @param[in] client_id Relying Party identification - * @param[in] psa_cert_ref PSA certification ID - * @param[in] token_buf Output buffer which will hold the resultant EAT in JSON format - * @param[in] token_buf_size Size of the output buffer - * @param[out] token_len Actual length of the output EAT JSON - * - * @return - * - `ESP_OK` on success - * - `ESP_ERR_INVALID_ARG` in case token_buf or token_len are NULL or token_buf_size is 0 - * - `ESP_ERR_NO_MEM` in case memory could not be allocated for the internal structures - * - `ESP_FAIL` other errors - */ -esp_err_t esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, - uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index 1a3bcf64cc..757b30931f 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include "esp_err.h" #include "esp_fault.h" #include "soc/soc_caps.h" @@ -24,6 +25,7 @@ #if SOC_ECC_SUPPORTED #include "ecc_impl.h" #endif +#include "psa/initial_attestation.h" #include "esp_crypto_periph_clk.h" #include "esp_tee.h" @@ -32,6 +34,9 @@ #include "esp_tee_sec_storage.h" #include "esp_tee_ota_ops.h" +#include "esp_attestation.h" + +#include "sdkconfig.h" static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv"; @@ -426,3 +431,49 @@ esp_err_t _ss_esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *c { return esp_tee_sec_storage_gen_key(cfg); } + +/* ---------------------------------------------- PSA Attestation ------------------------------------------------- */ + +__attribute__((unused)) static psa_status_t esp_err_to_psa_status(esp_err_t err) +{ + switch (err) { + case ESP_OK: + return PSA_SUCCESS; + case ESP_ERR_INVALID_ARG: + return PSA_ERROR_INVALID_ARGUMENT; + case ESP_ERR_INVALID_SIZE: + return PSA_ERROR_BUFFER_TOO_SMALL; + default: + return PSA_ERROR_GENERIC_ERROR; + } +} + +psa_status_t _ss_psa_initial_attest_get_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size) +{ +#if CONFIG_SECURE_TEE_ATTESTATION + bool valid_addr = (esp_tee_ptr_in_ree((void *)auth_challenge) && + esp_tee_ptr_in_ree((void *)token_buf) && + esp_tee_ptr_in_ree((void *)token_size)); + valid_addr &= (esp_tee_ptr_in_ree((void *)((uint8_t *)auth_challenge + challenge_size)) && + esp_tee_ptr_in_ree((void *)((uint8_t *)token_buf + token_buf_size))); + + if (!valid_addr) { + return PSA_ERROR_INVALID_ARGUMENT; + } + ESP_FAULT_ASSERT(valid_addr); + + return esp_err_to_psa_status(esp_att_generate_token(auth_challenge, challenge_size, token_buf, token_buf_size, token_size)); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif +} + +psa_status_t _ss_psa_initial_attest_get_token_size(size_t challenge_size, size_t *token_size) +{ +#if CONFIG_SECURE_TEE_ATTESTATION + return esp_err_to_psa_status(esp_att_get_token_size(challenge_size, token_size)); +#else + return PSA_ERROR_NOT_SUPPORTED; +#endif +} diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index c7bdf9d6e7..fc5b52bf46 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -188,7 +188,6 @@ endif() set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin) target_include_directories(tfpsacrypto PUBLIC "port/include") -target_include_directories(tfpsacrypto PRIVATE "port/psa_crypto_storage/include") if(CONFIG_MBEDTLS_HARDWARE_SHA OR CONFIG_MBEDTLS_HARDWARE_AES) target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include") @@ -241,6 +240,11 @@ if(NOT ${IDF_TARGET} STREQUAL "linux") endif() endif() +# PSA Attestation +if(CONFIG_SECURE_TEE_ATTESTATION) + target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_attestation/psa_initial_attestation.c") +endif() + if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) set(mbedtls_target_sources ${mbedtls_target_sources} "${COMPONENT_DIR}/port/dynamic/esp_mbedtls_dynamic_impl.c" diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake index 4641b77120..7324e97435 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake @@ -118,3 +118,6 @@ if(CONFIG_SOC_HMAC_SUPPORTED) # HMAC-based PBKDF2 implementation target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/esp_hmac_pbkdf2.c") endif() + +# PSA Attestation +target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_attestation") diff --git a/components/mbedtls/port/psa_crypto_storage/include/psa/error.h b/components/mbedtls/port/include/psa/error.h similarity index 100% rename from components/mbedtls/port/psa_crypto_storage/include/psa/error.h rename to components/mbedtls/port/include/psa/error.h diff --git a/components/mbedtls/port/include/psa/initial_attestation.h b/components/mbedtls/port/include/psa/initial_attestation.h new file mode 100644 index 0000000000..47d6c739f5 --- /dev/null +++ b/components/mbedtls/port/include/psa/initial_attestation.h @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * PSA Attestation implementation + */ + +#ifndef PSA_INITIAL_ATTESTATION_H +#define PSA_INITIAL_ATTESTATION_H + +#include +#include + +#include "psa/crypto_values.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR 1 /*!< Major version of this implementation of the Attestation API */ +#define PSA_INITIAL_ATTEST_API_VERSION_MINOR 0 /*!< Minor version of this implementation of the Attestation API */ + +#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE 2048 /*!< Maximum size of an attestation token in bytes */ + +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_MAX (PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) /*!< Maximum supported challenge size */ + +/** + * @brief Generate an entity attestation token + * + * Generates an attestation token containing device identity and security claims, signed and + * encoded in the JSON format. + * + * @param auth_challenge Pointer to a buffer containing the challenge data from the verifier + * @param challenge_size Size of the challenge in bytes. Must be 32, 48, or 64 bytes + * @param token_buf Pointer to a buffer where the attestation token will be written + * @param token_buf_size Size of the token buffer in bytes + * @param token_size On success, will be set to the actual size of the generated token + * + * @return psa_status_t PSA_SUCCESS on success, + * PSA_ERROR_INVALID_ARGUMENT if parameters are invalid, + * PSA_ERROR_BUFFER_TOO_SMALL if token_buf is too small, + * PSA_ERROR_NOT_SUPPORTED if the requested challenge size is not supported, + * or another error code on failure + */ +psa_status_t psa_initial_attest_get_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size); + +/** + * @brief Get the size of the attestation token that would be generated + * + * This can be used to allocate an appropriately sized buffer before calling psa_initial_attest_get_token(). + * + * @param challenge_size Size of the challenge in bytes. Must be 32, 48, or 64 bytes + * @param token_size On success, will be set to the size of the token that would be generated + * + * @return psa_status_t PSA_SUCCESS on success, + * PSA_ERROR_INVALID_ARGUMENT if challenge_size is invalid, + * PSA_ERROR_NOT_SUPPORTED if the requested challenge size is not supported, + * or another error code on failure + */ +psa_status_t psa_initial_attest_get_token_size(size_t challenge_size, size_t *token_size); + +#ifdef __cplusplus +} +#endif + +#endif // PSA_INITIAL_ATTESTATION_H diff --git a/components/mbedtls/port/psa_crypto_storage/include/psa/internal_trusted_storage.h b/components/mbedtls/port/include/psa/internal_trusted_storage.h similarity index 100% rename from components/mbedtls/port/psa_crypto_storage/include/psa/internal_trusted_storage.h rename to components/mbedtls/port/include/psa/internal_trusted_storage.h diff --git a/components/mbedtls/port/psa_attestation/psa_initial_attestation.c b/components/mbedtls/port/psa_attestation/psa_initial_attestation.c new file mode 100644 index 0000000000..83cd87e16e --- /dev/null +++ b/components/mbedtls/port/psa_attestation/psa_initial_attestation.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * PSA Attestation implementation + */ + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "psa/initial_attestation.h" + +#include +#include +#include + +#include "esp_log.h" + +static const char *TAG = "esp_psa_initial_attest"; + +/** + * @brief Dummy implementation of PSA attestation APIs + * + */ +psa_status_t psa_initial_attest_get_token(const uint8_t *auth_challenge, size_t challenge_size, + uint8_t *token_buf, size_t token_buf_size, size_t *token_size) +{ + ESP_LOGE(TAG, "Attestation service is not supported"); + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_initial_attest_get_token_size(size_t challenge_size, size_t *token_size) +{ + ESP_LOGE(TAG, "Attestation service is not supported"); + return PSA_ERROR_NOT_SUPPORTED; +}