refactor(esp_tee): Update TEE attestation tests and examples to use the PSA interface

This commit is contained in:
Laukik Hase
2026-01-16 12:28:58 +05:30
parent 89f555d698
commit 169f40658d
12 changed files with 300 additions and 90 deletions
@@ -4,7 +4,7 @@ set(priv_requires bootloader_support esp_driver_gptimer esp_tee esp_timer mbedtl
# Test FW related
list(APPEND priv_requires nvs_flash test_utils unity)
# TEE related
list(APPEND priv_requires tee_sec_storage tee_attestation tee_ota_ops test_sec_srv)
list(APPEND priv_requires tee_sec_storage tee_ota_ops test_sec_srv)
set(srcs "app_main.c")
@@ -1,8 +1,6 @@
dependencies:
ccomp_timer: "^1.0.0"
espressif/cjson: "^1.7.19"
tee_attestation:
path: ${IDF_PATH}/components/esp_tee/subproject/components/tee_attestation
tee_ota_ops:
path: ${IDF_PATH}/components/esp_tee/subproject/components/tee_ota_ops
tee_sec_storage:
@@ -1,17 +1,21 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025, Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2024-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <string.h>
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_random.h"
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "psa/crypto.h"
#include "psa/initial_attestation.h"
#include "esp_tee.h"
#include "esp_tee_attestation.h"
#include "secure_service_num.h"
#include "esp_tee_sec_storage.h"
@@ -19,6 +23,8 @@
#include "cJSON.h"
#include "unity.h"
#include "test_esp_tee_att_data.h"
/* Note: negative value here so that assert message prints a grep-able
error hex value (mbedTLS uses -N for error codes) */
#define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X))
@@ -27,14 +33,9 @@
#define SHA256_DIGEST_SZ (32)
#define ECDSA_SECP256R1_KEY_LEN (32)
#define ESP_ATT_TK_BUF_SIZE (1792)
#define ESP_ATT_TK_PSA_CERT_REF ("0632793520245-10010")
#define ESP_ATT_TK_NONCE (0xABCD1234)
#define ESP_ATT_TK_CLIENT_ID (0x0FACADE0)
static const char *TAG = "test_esp_tee_att";
__attribute__((unused)) static const char *TAG = "test_esp_tee_att";
/* Helper functions */
extern int verify_ecdsa_sign(const esp_tee_sec_storage_type_t key_type, const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign);
static uint8_t hexchar_to_byte(char hex)
@@ -244,17 +245,8 @@ static void fetch_signature(const char *token_json, esp_tee_sec_storage_ecdsa_si
cJSON_Delete(root);
}
TEST_CASE("Test TEE Attestation - Generate and verify the EAT", "[attestation]")
static void verify_attestation_token(const uint8_t *token_buf, size_t token_len)
{
uint8_t *token_buf = heap_caps_calloc(ESP_ATT_TK_BUF_SIZE, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(token_buf);
// Generating the attestation token
uint32_t token_len = 0;
TEST_ESP_OK(esp_tee_att_generate_token(0xA1B2C3D4, 0x0FACADE0, (const char *)ESP_ATT_TK_PSA_CERT_REF,
token_buf, ESP_ATT_TK_BUF_SIZE, &token_len));
ESP_LOGI(TAG, "EAT generated - length: %"PRIu32"", token_len);
// Pre-hashing the data
uint8_t digest[SHA256_DIGEST_SZ] = {};
prehash_token_data((const char *)token_buf, digest, sizeof(digest));
@@ -269,24 +261,92 @@ TEST_CASE("Test TEE Attestation - Generate and verify the EAT", "[attestation]")
// Verifying the generated token
TEST_ASSERT_EQUAL(0, verify_ecdsa_sign(ESP_SEC_STG_KEY_ECDSA_SECP256R1, digest, sizeof(digest), &pubkey_ctx, &sign_ctx));
free(token_buf);
}
TEST_CASE("Test TEE Attestation - Invalid token buffer", "[attestation]")
/* Test-cases */
int32_t psa_initial_attestation_get_token_test(void)
{
esp_err_t err;
uint32_t token_len = 0;
int num_checks = sizeof(check1) / sizeof(check1[0]);
psa_status_t status;
size_t token_buffer_size, token_size;
uint8_t challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 + 1];
uint8_t token_buffer[PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE];
uint8_t *token_buf = heap_caps_calloc(4, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(token_buf);
for (int i = 0; i < num_checks; i++) {
size_t challenge_size = check1[i].challenge_size;
err = esp_tee_att_generate_token(ESP_ATT_TK_NONCE, ESP_ATT_TK_CLIENT_ID, (const char *)ESP_ATT_TK_PSA_CERT_REF,
token_buf, 0, &token_len);
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, err);
printf("Check %d: ", i);
printf("%s", check1[i].test_desc);
err = esp_tee_att_generate_token(ESP_ATT_TK_NONCE, ESP_ATT_TK_CLIENT_ID, (const char *)ESP_ATT_TK_PSA_CERT_REF,
NULL, 0, &token_len);
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, err);
memset(challenge, 0x2a, sizeof(challenge));
memset(token_buffer, 0, sizeof(token_buffer));
free(token_buf);
status = psa_initial_attest_get_token_size(challenge_size, &token_buffer_size);
if (status != PSA_SUCCESS) {
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) {
token_buffer_size = check1[i].token_size;
challenge_size = check1[i].actual_challenge_size;
} else {
return status;
}
}
if (token_buffer_size > PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE) {
printf("Insufficient token buffer size\n");
return -1;
}
status = psa_initial_attest_get_token(challenge, challenge_size, token_buffer,
token_buffer_size, &token_size);
TEST_ASSERT_EQUAL_HEX32(check1[i].expected_status, status);
if (check1[i].expected_status != PSA_SUCCESS) {
continue;
}
/* Validate the token */
verify_attestation_token(token_buffer, token_size);
}
return 0;
}
int32_t psa_initial_attestation_get_token_size_test(void)
{
int num_checks = sizeof(check2) / sizeof(check2[0]);
psa_status_t status;
size_t token_size;
for (int i = 0; i < num_checks; i++) {
printf("Check %d: ", i);
printf("%s", check2[i].test_desc);
status = psa_initial_attest_get_token_size(check2[i].challenge_size, &token_size);
TEST_ASSERT_EQUAL_HEX32(check2[i].expected_status, status);
if (check2[i].expected_status != PSA_SUCCESS) {
continue;
}
if (token_size < check2[i].challenge_size) {
printf("Token size less than challenge size\n");
return -1;
}
}
return 0;
}
TEST_CASE("PSA Attestation: Test psa_initial_attestation_get_token", "[attestation]")
{
TEST_ASSERT_PSA_OK(psa_initial_attestation_get_token_test());
}
TEST_CASE("PSA Attestation: Test psa_initial_attestation_get_token_size", "[attestation]")
{
TEST_ASSERT_PSA_OK(psa_initial_attestation_get_token_size_test());
}
@@ -0,0 +1,123 @@
/*
* SPDX-FileCopyrightText: 2019-2023, Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
*/
#ifndef _TEST_DATA_H_
#define _TEST_DATA_H_
#include "psa/crypto_values.h"
#include "psa/initial_attestation.h"
/* Define TOKEN_SIZE and MAX_CHALLENGE_SIZE if not already defined */
#ifndef TOKEN_SIZE
#define TOKEN_SIZE PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE
#endif
#ifndef MAX_CHALLENGE_SIZE
#define MAX_CHALLENGE_SIZE PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64
#endif
typedef struct {
char test_desc[100];
size_t challenge_size;
size_t actual_challenge_size;
size_t token_size;
psa_status_t expected_status;
} test_data;
static const test_data check1[] = {
{
"Test psa_initial_attestation_get_token with Challenge 32\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token with Challenge 48\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token with Challenge 64\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token with zero challenge size\n",
0, 0, TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token with small challenge size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token with invalid challenge size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 1,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token with large challenge size\n",
MAX_CHALLENGE_SIZE + 1, MAX_CHALLENGE_SIZE + 1, TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token with zero as token size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32,
0, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token with small token size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32,
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1, PSA_ERROR_BUFFER_TOO_SMALL
},
};
static const test_data check2[] = {
{
"Test psa_initial_attestation_get_token_size with Challenge 32\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token_size with Challenge 48\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token_size with Challenge 64\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64, TOKEN_SIZE, PSA_SUCCESS
},
{
"Test psa_initial_attestation_get_token_size with zero challenge size\n",
0, 0,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token_size with small challenge size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 - 1,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token_size with invalid challenge size\n",
PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 1, PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 + 1,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
{
"Test psa_initial_attestation_get_token_size with large challenge size\n",
MAX_CHALLENGE_SIZE + 1, MAX_CHALLENGE_SIZE + 1,
TOKEN_SIZE, PSA_ERROR_INVALID_ARGUMENT
},
};
#endif /* _TEST_DATA_H_ */
@@ -13,9 +13,7 @@
#include "esp_tee.h"
#include "esp_tee_sec_storage.h"
#include "secure_service_num.h"
#if CONFIG_SECURE_TEE_ATTESTATION
#include "esp_tee_attestation.h"
#endif
#include "psa/initial_attestation.h"
#include "esp_random.h"
#include "nvs.h"
@@ -33,9 +31,6 @@
#define ECDSA_SECP256R1_KEY_LEN (32)
#define ECDSA_SECP192R1_KEY_LEN (24)
#define ESP_ATT_TK_BUF_SIZE (1792)
#define ESP_ATT_TK_PSA_CERT_REF ("0632793520245-10010")
#define MAX_SEC_STG_ITER (16)
static const char *TAG = "test_esp_tee_sec_storage";
@@ -527,13 +522,19 @@ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_ke
#endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN */
#if CONFIG_SECURE_TEE_ATTESTATION
uint8_t *token_buf = heap_caps_calloc(ESP_ATT_TK_BUF_SIZE, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
// Prepare authentication challenge (just the nonce/challenge data)
uint8_t auth_challenge[PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32];
size_t challenge_size = sizeof(auth_challenge);
esp_fill_random(auth_challenge, challenge_size);
size_t token_buf_size = 0;
TEST_ESP_OK(psa_initial_attest_get_token_size(challenge_size, &token_buf_size));
uint8_t *token_buf = heap_caps_calloc(token_buf_size, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(token_buf);
uint32_t token_len = 0;
TEST_ESP_OK(esp_tee_att_generate_token(0xA1B2C3D4, 0x0FACADE0, (const char *)ESP_ATT_TK_PSA_CERT_REF,
token_buf, ESP_ATT_TK_BUF_SIZE, &token_len));
size_t token_len = 0;
TEST_ESP_OK(psa_initial_attest_get_token(auth_challenge, challenge_size, token_buf, token_buf_size, &token_len));
free(token_buf);
const char *attest_key_id = "attest_key";