feat(mbedtls): migrates ESP-TEE with PSA APIs

This commit is contained in:
Ashish Sharma
2025-12-19 07:28:33 +08:00
parent c47caf4f0a
commit f306dbea84
175 changed files with 4213 additions and 2038 deletions
@@ -676,11 +676,11 @@ esp_err_t esp_srp_get_session_key(esp_srp_handle_t *hd, char *bytes_A, int len_A
goto error;
}
psa_status_t status = psa_crypto_init();
ESP_RETURN_ON_FALSE(status == PSA_SUCCESS, ESP_FAIL, TAG, "Failed to initialize PSA crypto: %d", status);
// psa_status_t status = psa_crypto_init();
// ESP_RETURN_ON_FALSE(status == PSA_SUCCESS, ESP_FAIL, TAG, "Failed to initialize PSA crypto: %d", status);
psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT;
status = psa_hash_setup(&hash_op, PSA_ALG_SHA_512);
psa_status_t status = psa_hash_setup(&hash_op, PSA_ALG_SHA_512);
ESP_RETURN_ON_FALSE(status == PSA_SUCCESS, ESP_FAIL, TAG, "Failed to setup hash operation: %d", status);
psa_hash_update(&hash_op, (unsigned char *)bytes_S, len_S);
size_t hash_len = 0;
@@ -9,9 +9,9 @@
#include "string.h"
#include "stdio.h"
#include "mbedtls/bignum.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/private/bignum.h"
// #include "mbedtls/entropy.h"
// #include "mbedtls/ctr_drbg.h"
#include "esp_random.h"
#ifdef __cplusplus
+10 -6
View File
@@ -25,11 +25,11 @@
#define ACCESS_ECDH(S, var) S->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(var)
#endif
#include <mbedtls/aes.h>
#include <mbedtls/sha256.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecdh.h>
// #include <mbedtls/aes.h>
// #include <mbedtls/sha256.h>
// #include <mbedtls/entropy.h>
// #include <mbedtls/ctr_drbg.h>
// #include <mbedtls/ecdh.h>
#include <mbedtls/error.h>
#include <mbedtls/constant_time.h>
#include "psa/crypto.h"
@@ -362,7 +362,11 @@ static esp_err_t handle_session_command0(session_t *cur_session,
ret = ESP_OK;
exit_cmd0:
// Clean up the key_id if it wasn't stored in the session
// This happens when key agreement fails before cur_session->key_id is assigned
if (ret != ESP_OK && key_id != 0 && cur_session->key_id != key_id) {
psa_destroy_key(key_id);
}
return ret;
}
+32 -82
View File
@@ -12,10 +12,10 @@
#include <esp_check.h>
#include <inttypes.h>
#include <mbedtls/gcm.h>
// #include <mbedtls/gcm.h>
#include <mbedtls/error.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
// #include <mbedtls/entropy.h>
// #include <mbedtls/ctr_drbg.h>
#include "psa/crypto.h"
#include <protocomm_security.h>
@@ -65,9 +65,7 @@ typedef struct session {
char *session_key;
uint16_t session_key_len;
uint8_t iv[AES_GCM_IV_SIZE];
/* mbedtls context data for AES-GCM */
// mbedtls_gcm_context ctx_gcm;
psa_cipher_operation_t ctx_gcm;
/* PSA key for AES-GCM */
psa_key_id_t key_id;
esp_srp_handle_t *srp_hd;
} session_t;
@@ -257,26 +255,24 @@ static esp_err_t handle_session_command1(session_t *cur_session,
hexdump("Initialization vector", (char *)cur_session->iv, AES_GCM_IV_SIZE);
/* Initialize crypto context */
cur_session->ctx_gcm = (psa_cipher_operation_t) {0};
/* Initialize AES-GCM key */
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, AES_GCM_TAG_LEN);
psa_key_id_t key_id = 0;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, AES_GCM_KEY_LEN);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, alg);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
status = psa_import_key(&key_attributes, (uint8_t *)cur_session->session_key, cur_session->session_key_len, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed with status=%d", status);
/* Use first 32 bytes (256 bits) of the session key for AES-GCM */
size_t aes_key_bytes = AES_GCM_KEY_LEN / 8;
if (cur_session->session_key_len < aes_key_bytes) {
ESP_LOGE(TAG, "Session key too short: %d bytes (need at least %zu bytes)", cur_session->session_key_len, aes_key_bytes);
free(device_proof);
return ESP_FAIL;
}
status = psa_cipher_encrypt_setup(&cur_session->ctx_gcm, key_id, alg);
status = psa_import_key(&key_attributes, (uint8_t *)cur_session->session_key, aes_key_bytes, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_encrypt_setup failed with status=%d", status);
ESP_LOGE(TAG, "psa_import_key failed with status=%d", status);
free(device_proof);
return ESP_FAIL;
}
@@ -289,9 +285,7 @@ static esp_err_t handle_session_command1(session_t *cur_session,
free(device_proof);
free(out);
free(out_resp);
psa_cipher_abort(&cur_session->ctx_gcm);
psa_destroy_key(key_id);
// mbedtls_gcm_free(&cur_session->ctx_gcm);
return ESP_ERR_NO_MEM;
}
@@ -395,13 +389,7 @@ static esp_err_t sec2_close_session(protocomm_security_handle_t handle, uint32_t
}
if (cur_session->state == SESSION_STATE_DONE) {
/* Free GCM context data */
// mbedtls_gcm_free(&cur_session->ctx_gcm);
psa_status_t status = psa_cipher_abort(&cur_session->ctx_gcm);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_abort failed with status=%d", status);
return ESP_FAIL;
}
/* Destroy the AES-GCM key */
psa_destroy_key(cur_session->key_id);
cur_session->key_id = 0;
}
@@ -492,45 +480,28 @@ static esp_err_t sec2_encrypt(protocomm_security_handle_t handle,
ESP_LOGE(TAG, "Failed to allocate encrypt buf len %d", *outlen);
return ESP_ERR_NO_MEM;
}
uint8_t gcm_tag[AES_GCM_TAG_LEN];
psa_status_t status;
status = psa_cipher_set_iv(&cur_session->ctx_gcm, cur_session->iv, AES_GCM_IV_SIZE);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_set_iv failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, AES_GCM_TAG_LEN);
size_t out_len = 0;
status = psa_cipher_update(&cur_session->ctx_gcm, inbuf, inlen, *outbuf, *outlen , &out_len);
status = psa_aead_encrypt(cur_session->key_id, alg,
cur_session->iv, AES_GCM_IV_SIZE,
NULL, 0, /* No additional data */
inbuf, inlen,
*outbuf, *outlen, &out_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_update failed with status=%d", status);
ESP_LOGE(TAG, "psa_aead_encrypt failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
if (out_len != inlen) {
ESP_LOGE(TAG, "psa_cipher_update output length mismatch: expected %zd, got %zu", inlen, out_len);
if (out_len != *outlen) {
ESP_LOGE(TAG, "psa_aead_encrypt output length mismatch: expected %zd, got %zu", *outlen, out_len);
free(*outbuf);
return ESP_FAIL;
}
status = psa_cipher_finish(&cur_session->ctx_gcm, gcm_tag, AES_GCM_TAG_LEN, &out_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_finish failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
if (out_len != AES_GCM_TAG_LEN) {
ESP_LOGE(TAG, "psa_cipher_finish output length mismatch: expected %d, got %zu", AES_GCM_TAG_LEN, out_len);
free(*outbuf);
return ESP_FAIL;
}
memcpy(*outbuf + inlen, gcm_tag, AES_GCM_TAG_LEN);
/* Increment counter value for next operation */
sec2_gcm_iv_counter_increment(cur_session->iv);
@@ -572,47 +543,26 @@ static esp_err_t sec2_decrypt(protocomm_security_handle_t handle,
}
psa_status_t status;
status = psa_cipher_set_iv(&cur_session->ctx_gcm, cur_session->iv, AES_GCM_IV_SIZE);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_set_iv failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, AES_GCM_TAG_LEN);
size_t out_len = 0;
status = psa_cipher_update(&cur_session->ctx_gcm, inbuf, inlen - AES_GCM_TAG_LEN, *outbuf, *outlen, &out_len);
status = psa_aead_decrypt(cur_session->key_id, alg,
cur_session->iv, AES_GCM_IV_SIZE,
NULL, 0, /* No additional data */
inbuf, inlen,
*outbuf, *outlen, &out_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_update failed with status=%d", status);
ESP_LOGE(TAG, "psa_aead_decrypt failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
if (out_len != *outlen) {
ESP_LOGE(TAG, "psa_cipher_update output length mismatch: expected %zd, got %zu", *outlen, out_len);
ESP_LOGE(TAG, "psa_aead_decrypt output length mismatch: expected %zd, got %zu", *outlen, out_len);
free(*outbuf);
return ESP_FAIL;
}
uint8_t gcm_tag[AES_GCM_TAG_LEN];
memcpy(gcm_tag, inbuf + (inlen - AES_GCM_TAG_LEN), AES_GCM_TAG_LEN);
status = psa_cipher_finish(&cur_session->ctx_gcm, gcm_tag, AES_GCM_TAG_LEN, &out_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_cipher_finish failed with status=%d", status);
free(*outbuf);
return ESP_FAIL;
}
if (out_len != 0) {
ESP_LOGE(TAG, "psa_cipher_finish output length mismatch: expected 0, got %zu", out_len);
free(*outbuf);
return ESP_FAIL;
}
if (*outbuf == NULL) {
ESP_LOGE(TAG, "Output buffer is NULL");
return ESP_ERR_INVALID_ARG;
}
/* Increment counter value for next operation */
sec2_gcm_iv_counter_increment(cur_session->iv);
+44 -27
View File
@@ -10,7 +10,7 @@
#include "memory_checks.h"
#include "esp_newlib.h"
#include "psa/crypto.h"
#include "mbedtls/aes.h"
// #include "mbedtls/aes.h"
#if SOC_SHA_SUPPORT_PARALLEL_ENG
#include "sha/sha_parallel_engine.h"
#else
@@ -21,18 +21,21 @@
/* setUp runs before every test */
void setUp(void)
{
// #if SOC_SHA_SUPPORTED
// // Execute esp_sha operation to allocate internal SHA semaphore (in case of ESP32)
// // and initial DMA setup memory which is considered as leaked otherwise
// const uint8_t input_buffer[64] = {0};
// uint8_t output_buffer[64];
// #if SOC_SHA_SUPPORT_SHA256
// esp_sha(SHA2_256, input_buffer, sizeof(input_buffer), output_buffer);
// #endif // SOC_SHA_SUPPORT_SHA256
// #if SOC_SHA_SUPPORT_SHA512
// esp_sha(SHA2_512, input_buffer, sizeof(input_buffer), output_buffer);
// #endif // SOC_SHA_SUPPORT_SHA512
// #endif // SOC_SHA_SUPPORTED
#if SOC_SHA_SUPPORTED
// Execute esp_sha operation to allocate internal SHA semaphore (in case of ESP32)
// and initial DMA setup memory which is considered as leaked otherwise
const uint8_t input_buffer[64] = {0};
uint8_t output_buffer[64];
#if SOC_SHA_SUPPORT_SHA1
esp_sha(SHA1, input_buffer, sizeof(input_buffer), output_buffer);
#endif // SOC_SHA_SUPPORT_SHA1
#if SOC_SHA_SUPPORT_SHA256
esp_sha(SHA2_256, input_buffer, sizeof(input_buffer), output_buffer);
#endif // SOC_SHA_SUPPORT_SHA256
#if SOC_SHA_SUPPORT_SHA512
esp_sha(SHA2_512, input_buffer, sizeof(input_buffer), output_buffer);
#endif // SOC_SHA_SUPPORT_SHA512
#endif // SOC_SHA_SUPPORTED
#if defined(CONFIG_MBEDTLS_HARDWARE_MPI)
esp_mpi_enable_hardware_hw_op();
@@ -40,21 +43,35 @@ void setUp(void)
#endif // CONFIG_MBEDTLS_HARDWARE_MPI
// #if SOC_AES_SUPPORTED
// // Execute mbedtls_aes_init operation to allocate AES interrupt
// // allocation memory which is considered as leak otherwise
// const uint8_t plaintext[16] = {0};
// uint8_t ciphertext[16];
// const uint8_t key[16] = { 0 };
// mbedtls_aes_context ctx;
// mbedtls_aes_init(&ctx);
// mbedtls_aes_setkey_enc(&ctx, key, 128);
// mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, ciphertext);
// mbedtls_aes_free(&ctx);
// #endif // SOC_AES_SUPPORTED
// Execute mbedtls_aes_init operation to allocate AES interrupt
// allocation memory which is considered as leak otherwise
const uint8_t plaintext[16] = {0};
uint8_t ciphertext[32];
const uint8_t key[16] = { 0 };
psa_status_t status;
psa_key_id_t key_id = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, key, sizeof(key), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
size_t output_len = 0;
status = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING, plaintext, sizeof(plaintext), ciphertext, sizeof(ciphertext), &output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
const uint8_t plaintext_long[256] = {0};
uint8_t ciphertext_long[272];
output_len = 0;
status = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING, plaintext_long, sizeof(plaintext_long), ciphertext_long, sizeof(ciphertext_long), &output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
psa_destroy_key(key_id);
#endif // SOC_AES_SUPPORTED
test_utils_record_free_mem();
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_GENERAL));
TEST_ESP_OK(test_utils_set_leak_level(50, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
TEST_ESP_OK(test_utils_set_leak_level(50, ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_GENERAL));
}
/* tearDown runs after every test */
@@ -66,7 +83,7 @@ void tearDown(void)
/* clean up some of the newlib's lazy allocations */
esp_reent_cleanup();
mbedtls_psa_crypto_free();
// mbedtls_psa_crypto_free();
/* check if unit test has caused heap corruption in any heap */
TEST_ASSERT_MESSAGE( heap_caps_check_integrity(MALLOC_CAP_INVALID, true), "The test has corrupted the heap");
@@ -31,11 +31,11 @@
#endif
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include <mbedtls/aes.h>
#include <mbedtls/sha256.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecdh.h>
// #include <mbedtls/aes.h>
// #include <mbedtls/sha256.h>
// #include <mbedtls/entropy.h>
// #include <mbedtls/ctr_drbg.h>
// #include <mbedtls/ecdh.h>
#include <mbedtls/error.h>
#include "psa/crypto.h"
#include <protocomm.h>
@@ -1142,7 +1142,6 @@ TEST_CASE("leak test", "[PROTOCOMM]")
* time allocations to happen (not related to protocomm) */
test_security0();
test_security1();
mbedtls_psa_crypto_free();
usleep(1000);
#ifdef CONFIG_HEAP_TRACING
@@ -1153,7 +1152,6 @@ TEST_CASE("leak test", "[PROTOCOMM]")
/* Run all tests passively. Any leaks due
* to protocomm should show up now */
unsigned pre_start_mem = esp_get_free_heap_size();
psa_crypto_init();
test_security0();
test_security1();
test_security1_no_encryption();
@@ -1161,7 +1159,6 @@ TEST_CASE("leak test", "[PROTOCOMM]")
test_security1_wrong_pop();
test_security1_insecure_client();
test_security1_weak_session();
mbedtls_psa_crypto_free();
usleep(1000);
@@ -1181,36 +1178,36 @@ TEST_CASE("security 0 basic test", "[PROTOCOMM]")
TEST_CASE("security 1 basic test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1() == ESP_OK);
}
TEST_CASE("security 1 no encryption test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1_no_encryption() == ESP_OK);
}
TEST_CASE("security 1 session overflow test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1_session_overflow() == ESP_OK);
}
TEST_CASE("security 1 wrong pop test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1_wrong_pop() == ESP_OK);
}
TEST_CASE("security 1 insecure client test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1_insecure_client() == ESP_OK);
}
TEST_CASE("security 1 weak session test", "[PROTOCOMM]")
{
psa_crypto_init();
// psa_crypto_init();
TEST_ASSERT(test_security1_weak_session() == ESP_OK);
}