feat(esp_tee): Migrate TEE attestation to the PSA interface

This commit is contained in:
Laukik Hase
2025-12-31 12:00:41 +05:30
parent 5fe2a941f5
commit 89f555d698
22 changed files with 323 additions and 212 deletions
+2 -2
View File
@@ -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")
+9
View File
@@ -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
@@ -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:
@@ -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:
@@ -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:
@@ -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:
@@ -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
+1 -1
View File
@@ -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}")
@@ -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);
@@ -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;
}
@@ -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
}
@@ -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
*/
@@ -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})
@@ -1,55 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#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
@@ -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
@@ -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 <stdarg.h>
#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
}
+5 -1
View File
@@ -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"
@@ -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")
@@ -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 <stddef.h>
#include <stdint.h>
#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
@@ -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 <limits.h>
#include <stdint.h>
#include <string.h>
#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;
}