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 c0810ff45f7..7fb2c91041b 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-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -174,8 +174,31 @@ esp_err_t esp_att_utils_eat_data_to_json(struct esp_att_sw_claim_list *head, con free(auth_challenge_hexstr); json_gen_obj_set_int(&json_gen, "client_id", cfg->client_id); + json_gen_obj_set_int(&json_gen, "chip_id", cfg->chip_id); json_gen_obj_set_int(&json_gen, "device_ver", cfg->device_ver); + json_gen_push_object(&json_gen, "ueid"); + + char mac_hexstr[ESP_ATT_EAT_UEID_MAC_SZ * 2 + 1] = {0}; + err = esp_att_utils_hexbuf_to_hexstr(cfg->ueid_mac, sizeof(cfg->ueid_mac), + mac_hexstr, sizeof(mac_hexstr)); + if (err != ESP_OK) { + free(json_buf); + return err; + } + json_gen_obj_set_string(&json_gen, "mac", mac_hexstr); + + char opt_id_hexstr[ESP_ATT_EAT_UEID_OPT_ID_SZ * 2 + 1] = {0}; + err = esp_att_utils_hexbuf_to_hexstr(cfg->ueid_opt_id, sizeof(cfg->ueid_opt_id), + opt_id_hexstr, sizeof(opt_id_hexstr)); + if (err != ESP_OK) { + free(json_buf); + return err; + } + json_gen_obj_set_string(&json_gen, "optional_id", opt_id_hexstr); + + json_gen_pop_object(&json_gen); + char dev_id_hexstr[ESP_ATT_EAT_DEV_ID_SZ * 2 + 1] = {0}; 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) { @@ -201,6 +224,7 @@ esp_err_t esp_att_utils_eat_data_to_json(struct esp_att_sw_claim_list *head, con esp_err_t err = part_metadata_to_json(&claim->metadata, &claim_json); if (err != ESP_OK || claim_json == NULL) { ESP_LOGE(TAG, "Failed to format the FW metadata to JSON!"); + free(json_buf); return err; } diff --git a/components/esp_tee/subproject/components/attestation/esp_attestation.c b/components/esp_tee/subproject/components/attestation/esp_attestation.c index c239e826811..4f25ec5f614 100644 --- a/components/esp_tee/subproject/components/attestation/esp_attestation.c +++ b/components/esp_tee/subproject/components/attestation/esp_attestation.c @@ -48,44 +48,23 @@ static void free_sw_claim_list(void) } } -static esp_err_t fetch_device_id(uint8_t *devid_buf) +static esp_err_t fetch_ueids(esp_att_token_cfg_t *cfg) { - if (devid_buf == NULL) { - return ESP_ERR_INVALID_ARG; - } - - uint8_t mac_addr[6] = {0}; - esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_MAC, mac_addr, sizeof(mac_addr) * 8); + /* UEID: raw eFuse MAC */ + esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_MAC, cfg->ueid_mac, + ESP_ATT_EAT_UEID_MAC_SZ * 8); if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to read MAC from eFuse!"); - goto exit; + return err; } - psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT; - psa_status_t status = psa_hash_setup(&hash_op, PSA_ALG_SHA_256); - if (status != PSA_SUCCESS) { - return ESP_FAIL; - } - - status = psa_hash_update(&hash_op, mac_addr, sizeof(mac_addr)); - if (status != PSA_SUCCESS) { - return ESP_FAIL; - } - - size_t digest_len = 0; - status = psa_hash_finish(&hash_op, devid_buf, SHA256_DIGEST_SZ, &digest_len); - if (status != PSA_SUCCESS) { - return ESP_FAIL; - } - - if (digest_len != SHA256_DIGEST_SZ) { - return ESP_ERR_INVALID_SIZE; + /* UEID: 128-bit OPTIONAL_UNIQUE_ID */ + err = esp_efuse_read_field_blob(ESP_EFUSE_OPTIONAL_UNIQUE_ID, cfg->ueid_opt_id, + ESP_ATT_EAT_UEID_OPT_ID_SZ * 8); + if (err != ESP_OK) { + return err; } return ESP_OK; - -exit: - return err; } static esp_err_t populate_att_token_cfg(esp_att_token_cfg_t *cfg, const esp_att_ecdsa_keypair_t *keypair) @@ -94,18 +73,31 @@ static esp_err_t populate_att_token_cfg(esp_att_token_cfg_t *cfg, const esp_att_ return ESP_ERR_INVALID_ARG; } - esp_err_t err = fetch_device_id(cfg->device_id); + esp_err_t err = fetch_ueids(cfg); if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to get the device ID!"); + ESP_LOGE(TAG, "Failed to get the UEIDs!"); return err; } + /* Device ID = SHA-256 of the MAC */ + size_t digest_len = 0; + psa_status_t status = psa_hash_compute(PSA_ALG_SHA_256, cfg->ueid_mac, sizeof(cfg->ueid_mac), + cfg->device_id, sizeof(cfg->device_id), &digest_len); + if (status != PSA_SUCCESS || digest_len != sizeof(cfg->device_id)) { + ESP_LOGE(TAG, "Failed to derive the device ID!"); + return ESP_FAIL; + } + err = esp_att_utils_ecdsa_get_pubkey_digest(keypair, cfg->instance_id, sizeof(cfg->instance_id)); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to get ECDSA public key hash!"); return err; } + /* Chip ID read from the ROM */ + extern const uint32_t _rom_chip_id; + cfg->chip_id = _rom_chip_id; + /* Chip revision read from eFuse */ cfg->device_ver = efuse_hal_chip_revision(); /* TODO: Decide what all fields we need here */ cfg->device_stat = 0xA5; @@ -191,6 +183,13 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge } esp_att_ecdsa_keypair_t keypair = {}; + psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT; + psa_status_t status; + char *hdr_json = NULL; + char *eat_json = NULL; + char *pubkey_json = NULL; + char *sign_json = NULL; + err = esp_att_utils_ecdsa_gen_keypair_secp256r1(&keypair); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate ECDSA key-pair!"); @@ -214,10 +213,10 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge memset(token_buf, 0x00, token_buf_size); - psa_hash_operation_t hash_op = PSA_HASH_OPERATION_INIT; - psa_status_t status = psa_hash_setup(&hash_op, PSA_ALG_SHA_256); + status = psa_hash_setup(&hash_op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { - return ESP_FAIL; + err = ESP_FAIL; + goto exit; } json_gen_str_t jstr; @@ -226,79 +225,84 @@ esp_err_t esp_att_generate_token(const uint8_t *auth_challenge, size_t challenge /* Pushing the Header object */ const esp_att_token_hdr_t tk_hdr = {}; - char *hdr_json = NULL; int hdr_len = -1; /* NOTE: Token header is not yet configurable */ err = esp_att_utils_header_to_json(&tk_hdr, &hdr_json, &hdr_len); - if (err != ESP_OK || hdr_json == NULL || hdr_len <= 0) { + if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to format the token header as JSON!"); - return err; + goto exit; } json_gen_push_object_str(&jstr, "header", hdr_json); status = psa_hash_update(&hash_op, (const unsigned char *)hdr_json, hdr_len - 1); if (status != PSA_SUCCESS) { - psa_hash_abort(&hash_op); - return ESP_FAIL; + err = ESP_FAIL; + goto exit; } free(hdr_json); + hdr_json = NULL; /* Pushing the EAT object */ - char *eat_json = NULL; int eat_len = -1; err = esp_att_utils_eat_data_to_json(&sw_claim_data, &cfg, &eat_json, &eat_len); - if (err != ESP_OK || eat_json == NULL || eat_len <= 0) { + if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to format the EAT data to JSON!"); - return err; + goto exit; } json_gen_push_object_str(&jstr, "eat", eat_json); status = psa_hash_update(&hash_op, (const unsigned char *)eat_json, eat_len - 1); if (status != PSA_SUCCESS) { - psa_hash_abort(&hash_op); - return ESP_FAIL; + err = ESP_FAIL; + goto exit; } free(eat_json); + eat_json = NULL; - char *pubkey_json = NULL; int pubkey_len = -1; err = esp_att_utils_pubkey_to_json(&keypair, &pubkey_json, &pubkey_len); - if (err != ESP_OK || pubkey_json == NULL || pubkey_len <= 0) { + if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to format the public key data to JSON!"); - return err; + goto exit; } json_gen_push_object_str(&jstr, "public_key", pubkey_json); status = psa_hash_update(&hash_op, (const unsigned char *)pubkey_json, pubkey_len - 1); if (status != PSA_SUCCESS) { - psa_hash_abort(&hash_op); - return ESP_FAIL; + err = ESP_FAIL; + goto exit; } free(pubkey_json); + pubkey_json = NULL; uint8_t digest[SHA256_DIGEST_SZ] = {0}; size_t digest_len = 0; status = psa_hash_finish(&hash_op, digest, sizeof(digest), &digest_len); if (status != PSA_SUCCESS) { - psa_hash_abort(&hash_op); - return ESP_FAIL; + err = ESP_FAIL; + goto exit; } - char *sign_json = NULL; int sign_len = -1; err = esp_att_utils_sign_to_json(&keypair, digest, sizeof(digest), &sign_json, &sign_len); - if (err != ESP_OK || sign_json == NULL || sign_len <= 0) { + if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to format the token signature to JSON!"); - return err; + goto exit; } json_gen_push_object_str(&jstr, "sign", sign_json); free(sign_json); + sign_json = NULL; json_gen_end_object(&jstr); *token_size = json_gen_str_end(&jstr); err = ESP_OK; exit: + psa_hash_abort(&hash_op); + free(hdr_json); + free(eat_json); + free(pubkey_json); + free(sign_json); free_sw_claim_list(); return err; } 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 50c90e57608..a8043554333 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 @@ -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 */ @@ -37,8 +37,10 @@ extern "C" { #define ESP_ATT_HDR_JSON_MAX_SZ (128) #define ESP_ATT_EAT_DEV_ID_SZ (32) +#define ESP_ATT_EAT_UEID_MAC_SZ (6) /* eFuse MAC */ +#define ESP_ATT_EAT_UEID_OPT_ID_SZ (16) /* eFuse OPTIONAL_UNIQUE_ID */ #define ESP_ATT_CLAIM_JSON_MAX_SZ (448) -#define ESP_ATT_EAT_JSON_MAX_SZ (1344) +#define ESP_ATT_EAT_JSON_MAX_SZ (1600) #define ESP_ATT_PUBKEY_JSON_MAX_SZ (128) #define ESP_ATT_SIGN_JSON_MAX_SZ (192) @@ -119,14 +121,17 @@ typedef struct { * @brief Structure to hold the Entity Attestation Token initial configuration */ typedef struct { - 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 */ - uint8_t instance_id[SHA256_DIGEST_SZ]; /**< Instance identifier */ - char psa_cert_ref[32]; /**< PSA certificate reference */ - uint8_t device_stat; /**< Flags indicating device status */ + uint8_t *auth_challenge; /**< Authentication challenge */ + size_t challenge_size; /**< Challenge size */ + uint32_t client_id; /**< Client identifier (Attestation relying party) */ + uint32_t chip_id; /**< Chip identifier */ + uint32_t device_ver; /**< Device version */ + uint8_t ueid_mac[ESP_ATT_EAT_UEID_MAC_SZ]; /**< Device UEID: MAC from eFuse*/ + uint8_t ueid_opt_id[ESP_ATT_EAT_UEID_OPT_ID_SZ]; /**< Device UEID: OPTIONAL_UNIQUE_ID from eFuse*/ + uint8_t device_id[SHA256_DIGEST_SZ]; /**< Device identifier (SHA-256 of MAC) */ + uint8_t instance_id[SHA256_DIGEST_SZ]; /**< Instance identifier */ + char psa_cert_ref[32]; /**< PSA certificate reference */ + uint8_t device_stat; /**< Flags indicating device status */ } esp_att_token_cfg_t; /** diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c index f0f3742bf48..d9bf42a9d0e 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c @@ -22,6 +22,7 @@ #include "esp_hmac_pbkdf2.h" #include "psa/crypto.h" +#include "mbedtls/platform_util.h" #include "mbedtls/psa_util.h" #include "esp_rom_sys.h" @@ -193,7 +194,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c psa_reset_key_attributes(&attributes); // Zero out the key buffer after import - memset(key_buf, 0x00, sizeof(key_buf)); + mbedtls_platform_zeroize(key_buf, sizeof(key_buf)); if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "Failed to import HMAC key: %d", status); @@ -208,7 +209,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c (uint8_t *)cfg->eky, SHA256_DIGEST_SZ, &mac_length); if (status != PSA_SUCCESS) { psa_destroy_key(psa_key_id); - memset(cfg, 0x00, sizeof(nvs_sec_cfg_t)); + mbedtls_platform_zeroize(cfg, sizeof(nvs_sec_cfg_t)); return ESP_FAIL; } ESP_FAULT_ASSERT(status == PSA_SUCCESS); @@ -221,7 +222,7 @@ static esp_err_t compute_nvs_keys_with_hmac(esp_efuse_block_t key_blk, nvs_sec_c psa_destroy_key(psa_key_id); if (status != PSA_SUCCESS) { - memset(cfg, 0x00, sizeof(nvs_sec_cfg_t)); + mbedtls_platform_zeroize(cfg, sizeof(nvs_sec_cfg_t)); return ESP_FAIL; } ESP_FAULT_ASSERT(status == PSA_SUCCESS); @@ -322,20 +323,24 @@ esp_err_t esp_tee_sec_storage_clear_key(const char *key_id) esp_err_t err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len); if (err != ESP_OK) { - return err; + goto cleanup; } if (keyctx.flags & SEC_STORAGE_FLAG_WRITE_ONCE) { ESP_LOGE(TAG, "Key is write-once only and cannot be cleared!"); - return ESP_ERR_INVALID_STATE; + err = ESP_ERR_INVALID_STATE; + goto cleanup; } err = nvs_erase_key(tee_nvs_hdl, key_id); if (err != ESP_OK) { - return err; + goto cleanup; } err = nvs_commit(tee_nvs_hdl); + +cleanup: + mbedtls_platform_zeroize(&keyctx, sizeof(keyctx)); return err; } @@ -465,6 +470,7 @@ esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg) return ESP_ERR_INVALID_STATE; } + esp_err_t err; sec_stg_key_t keyctx = { .type = cfg->type, .flags = cfg->flags, @@ -477,21 +483,28 @@ esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg) #endif if (generate_ecdsa_key(&keyctx, cfg->type) != 0) { ESP_LOGE(TAG, "Failed to generate ECDSA keypair"); - return ESP_FAIL; + err = ESP_FAIL; + goto cleanup; } break; case ESP_SEC_STG_KEY_AES256: if (generate_aes256_key(&keyctx) != 0) { ESP_LOGE(TAG, "Failed to generate AES key"); - return ESP_FAIL; + err = ESP_FAIL; + goto cleanup; } break; default: ESP_LOGE(TAG, "Unsupported key-type!"); - return ESP_ERR_NOT_SUPPORTED; + err = ESP_ERR_NOT_SUPPORTED; + goto cleanup; } - return secure_storage_write(cfg->id, (void *)&keyctx, sizeof(keyctx)); + err = secure_storage_write(cfg->id, (void *)&keyctx, sizeof(keyctx)); + +cleanup: + mbedtls_platform_zeroize(&keyctx, sizeof(keyctx)); + return err; } esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign) @@ -514,19 +527,21 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf sec_stg_key_t keyctx; size_t keyctx_len = sizeof(keyctx); + psa_key_id_t key_id = 0; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to fetch key from storage"); - return err; + goto exit; } if (keyctx.type != cfg->type) { ESP_LOGE(TAG, "Key type mismatch"); - return ESP_ERR_INVALID_STATE; + err = ESP_ERR_INVALID_STATE; + goto exit; } - 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_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH); psa_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256); @@ -571,6 +586,7 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf exit: psa_destroy_key(key_id); psa_reset_key_attributes(&key_attributes); + mbedtls_platform_zeroize(&keyctx, sizeof(keyctx)); return err; } @@ -594,12 +610,13 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to read key from secure storage"); - return err; + goto cleanup; } if (keyctx.type != cfg->type) { ESP_LOGE(TAG, "Key type mismatch"); - return ESP_ERR_INVALID_STATE; + err = ESP_ERR_INVALID_STATE; + goto cleanup; } /* Now determine the public key source and length based on key type */ @@ -619,13 +636,17 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg #endif default: ESP_LOGE(TAG, "Unsupported key-type"); - return ESP_ERR_INVALID_ARG; + err = ESP_ERR_INVALID_ARG; + goto cleanup; } memcpy(out_pubkey->pub_x, pub_key_src, pub_key_len); memcpy(out_pubkey->pub_y, pub_key_src + pub_key_len, pub_key_len); + err = ESP_OK; - return ESP_OK; +cleanup: + mbedtls_platform_zeroize(&keyctx, sizeof(keyctx)); + return err; } static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t *input, size_t len, const uint8_t *aad, @@ -648,17 +669,22 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t return err; } + psa_key_id_t psa_key_id = 0; + uint8_t *aead_buf = NULL; + size_t aead_buf_len = 0; + sec_stg_key_t keyctx; size_t keyctx_len = sizeof(keyctx); err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to fetch key from storage"); - return err; + goto cleanup; } if (keyctx.type != ESP_SEC_STG_KEY_AES256) { ESP_LOGE(TAG, "Key type mismatch"); - return ESP_ERR_INVALID_STATE; + err = ESP_ERR_INVALID_STATE; + goto cleanup; } // Setup PSA key attributes @@ -670,70 +696,66 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); // Import the AES key - psa_key_id_t key_id_psa = 0; - psa_status_t status = psa_import_key(&attributes, keyctx.aes256.key, AES256_KEY_LEN, &key_id_psa); + psa_status_t status = psa_import_key(&attributes, keyctx.aes256.key, AES256_KEY_LEN, &psa_key_id); psa_reset_key_attributes(&attributes); if (status != PSA_SUCCESS) { - return ESP_FAIL; + err = ESP_FAIL; + goto cleanup; + } + + /* PSA AEAD wants ciphertext+tag concatenated in a single buffer for both + * encrypt (output) and decrypt (input). */ + aead_buf_len = len + tag_len; + aead_buf = malloc(aead_buf_len); + if (!aead_buf) { + err = ESP_ERR_NO_MEM; + goto cleanup; } if (is_encrypt) { - // PSA AEAD encrypt outputs ciphertext+tag concatenated - uint8_t *output_with_tag = malloc(len + tag_len); - if (!output_with_tag) { - psa_destroy_key(key_id_psa); - return ESP_ERR_NO_MEM; - } - esp_fill_random(iv, iv_len); size_t output_length = 0; - status = psa_aead_encrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len), + status = psa_aead_encrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len), iv, iv_len, aad, aad_len, input, len, - output_with_tag, len + tag_len, &output_length); + aead_buf, aead_buf_len, &output_length); if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "Error in encrypting data: %d", status); - memset(output_with_tag, 0x00, len + tag_len); - free(output_with_tag); - psa_destroy_key(key_id_psa); - return ESP_FAIL; + err = ESP_FAIL; + goto cleanup; } // Separate ciphertext and tag - memcpy(output, output_with_tag, len); - memcpy(tag, output_with_tag + len, tag_len); - - memset(output_with_tag, 0x00, len + tag_len); - free(output_with_tag); + memcpy(output, aead_buf, len); + memcpy(tag, aead_buf + len, tag_len); } else { - // For decryption, PSA expects ciphertext + tag concatenated - uint8_t *input_with_tag = malloc(len + tag_len); - if (!input_with_tag) { - psa_destroy_key(key_id_psa); - return ESP_ERR_NO_MEM; - } - - memcpy(input_with_tag, input, len); - memcpy(input_with_tag + len, tag, tag_len); + memcpy(aead_buf, input, len); + memcpy(aead_buf + len, tag, tag_len); size_t output_length = 0; - status = psa_aead_decrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len), - iv, iv_len, aad, aad_len, input_with_tag, len + tag_len, + status = psa_aead_decrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len), + iv, iv_len, aad, aad_len, aead_buf, aead_buf_len, output, len, &output_length); - - memset(input_with_tag, 0x00, len + tag_len); - free(input_with_tag); - if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "Error in decrypting data: %d", status); - psa_destroy_key(key_id_psa); - return ESP_FAIL; + err = ESP_FAIL; + goto cleanup; } } - psa_destroy_key(key_id_psa); - return ESP_OK; + err = ESP_OK; + +cleanup: + if (aead_buf) { + mbedtls_platform_zeroize(aead_buf, aead_buf_len); + free(aead_buf); + } + if (psa_key_id != 0) { + psa_destroy_key(psa_key_id); + } + mbedtls_platform_zeroize(&keyctx, sizeof(keyctx)); + return err; } esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output) @@ -819,24 +841,20 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2 } // Sign the hash - memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t)); size_t signature_length = 0; status = psa_sign_hash(psa_key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hlen, out_sign->signature, sizeof(out_sign->signature), &signature_length); if (status != PSA_SUCCESS) { - memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t)); err = ESP_FAIL; goto exit; } // Export public key - memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)); uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; size_t public_key_length = 0; status = psa_export_public_key(psa_key_id, public_key, sizeof(public_key), &public_key_length); if (status != PSA_SUCCESS) { - memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)); err = ESP_FAIL; goto exit; } @@ -844,7 +862,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2 // PSA exports public key in uncompressed format: 0x04 || X || Y // Skip the first byte (0x04) and copy X and Y coordinates if (public_key_length != (1 + 2 * key_len) || public_key[0] != 0x04) { - memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)); err = ESP_FAIL; goto exit; } @@ -859,7 +876,7 @@ exit: psa_destroy_key(psa_key_id); } if (derived_key) { - memset(derived_key, 0x00, key_len); + mbedtls_platform_zeroize(derived_key, key_len); free(derived_key); } return err; diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_asm_utils.inc b/components/esp_tee/subproject/main/arch/riscv/esp_tee_asm_utils.inc new file mode 100644 index 00000000000..6478f02e13a --- /dev/null +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_asm_utils.inc @@ -0,0 +1,223 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Shared assembly helpers (macros + assembler-time constants) for the TEE + * M-mode runtime. Included from esp_tee_vectors_{plic,clic}.S + */ + +#pragma once + +#include "sdkconfig.h" +#include "riscv/rvruntime-frames.h" + +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD +#include "esp_private/hw_stack_guard.h" +#endif + +/* Shared assembler-time constants used by the macros */ +.equ SAVE_REGS, 32 +.equ CONTEXT_SIZE, (SAVE_REGS * 4) +.equ MAGIC, 0x1f + +/* Macro which first allocates space on the stack to save general + * purpose registers, and then save them. GP register is excluded. + * The default size allocated on the stack is CONTEXT_SIZE, but it + * can be overridden. */ +.macro save_general_regs cxt_size=CONTEXT_SIZE + addi sp, sp, -\cxt_size + sw ra, RV_STK_RA(sp) + sw tp, RV_STK_TP(sp) + sw t0, RV_STK_T0(sp) + sw t1, RV_STK_T1(sp) + sw t2, RV_STK_T2(sp) + sw s0, RV_STK_S0(sp) + sw s1, RV_STK_S1(sp) + sw a0, RV_STK_A0(sp) + sw a1, RV_STK_A1(sp) + sw a2, RV_STK_A2(sp) + sw a3, RV_STK_A3(sp) + sw a4, RV_STK_A4(sp) + sw a5, RV_STK_A5(sp) + sw a6, RV_STK_A6(sp) + sw a7, RV_STK_A7(sp) + sw s2, RV_STK_S2(sp) + sw s3, RV_STK_S3(sp) + sw s4, RV_STK_S4(sp) + sw s5, RV_STK_S5(sp) + sw s6, RV_STK_S6(sp) + sw s7, RV_STK_S7(sp) + sw s8, RV_STK_S8(sp) + sw s9, RV_STK_S9(sp) + sw s10, RV_STK_S10(sp) + sw s11, RV_STK_S11(sp) + sw t3, RV_STK_T3(sp) + sw t4, RV_STK_T4(sp) + sw t5, RV_STK_T5(sp) + sw t6, RV_STK_T6(sp) +.endm + +.macro save_mepc + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) +.endm + +.macro save_mcsr + csrr t0, mstatus + sw t0, RV_STK_MSTATUS(sp) + csrr t0, mtvec + sw t0, RV_STK_MTVEC(sp) + csrr t0, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) + csrr t0, mcause + sw t0, RV_STK_MCAUSE(sp) +.endm + +/* Restore the general purpose registers (excluding gp) from the context on + * the stack. The context is then deallocated. The default size is CONTEXT_SIZE + * but it can be overridden. */ +.macro restore_general_regs cxt_size=CONTEXT_SIZE + lw ra, RV_STK_RA(sp) + lw tp, RV_STK_TP(sp) + lw t0, RV_STK_T0(sp) + lw t1, RV_STK_T1(sp) + lw t2, RV_STK_T2(sp) + lw s0, RV_STK_S0(sp) + lw s1, RV_STK_S1(sp) + lw a0, RV_STK_A0(sp) + lw a1, RV_STK_A1(sp) + lw a2, RV_STK_A2(sp) + lw a3, RV_STK_A3(sp) + lw a4, RV_STK_A4(sp) + lw a5, RV_STK_A5(sp) + lw a6, RV_STK_A6(sp) + lw a7, RV_STK_A7(sp) + lw s2, RV_STK_S2(sp) + lw s3, RV_STK_S3(sp) + lw s4, RV_STK_S4(sp) + lw s5, RV_STK_S5(sp) + lw s6, RV_STK_S6(sp) + lw s7, RV_STK_S7(sp) + lw s8, RV_STK_S8(sp) + lw s9, RV_STK_S9(sp) + lw s10, RV_STK_S10(sp) + lw s11, RV_STK_S11(sp) + lw t3, RV_STK_T3(sp) + lw t4, RV_STK_T4(sp) + lw t5, RV_STK_T5(sp) + lw t6, RV_STK_T6(sp) + addi sp, sp, \cxt_size +.endm + +.macro restore_mepc + lw t0, RV_STK_MEPC(sp) + csrw mepc, t0 +.endm + +.macro store_magic_general_regs + lui ra, MAGIC + lui tp, MAGIC + lui t0, MAGIC + lui t1, MAGIC + lui t2, MAGIC + lui s0, MAGIC + lui s1, MAGIC + lui a0, MAGIC + lui a1, MAGIC + lui a2, MAGIC + lui a3, MAGIC + lui a4, MAGIC + lui a5, MAGIC + lui a6, MAGIC + lui a7, MAGIC + lui s2, MAGIC + lui s3, MAGIC + lui s4, MAGIC + lui s5, MAGIC + lui s6, MAGIC + lui s7, MAGIC + lui s8, MAGIC + lui s9, MAGIC + lui s10, MAGIC + lui s11, MAGIC + lui t3, MAGIC + lui t4, MAGIC + lui t5, MAGIC + lui t6, MAGIC +.endm + +/** + * STACK_GUARD_PRE_SWITCH + * Stops HW stack-guard monitoring and optionally saves current bounds. + * + * Args: + * op_reg – output register for "monitoring enabled" state (must be reused) + * to_save – 1=save bounds to memory, 0=skip saving + * sp_min – symbol to store lower bound (if to_save=1) + * sp_max – symbol to store upper bound (if to_save=1) + * + * Clobbers: t0, t1, t2, op_reg + */ +.macro STACK_GUARD_PRE_SWITCH op_reg, to_save, sp_min, sp_max +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + /* Query if monitoring is enabled: result goes into \op_reg */ + ESP_HW_STACK_GUARD_MONITOR_QUERY_CUR_CORE t2 \op_reg + beqz \op_reg, 1f + + .if \to_save + /* Save current REE/U-mode stack bounds */ + ESP_HW_STACK_GUARD_GET_BOUNDS_CUR_CORE t2 t0 t1 + la t2, \sp_min + sw t0, 0(t2) + la t2, \sp_max + sw t1, 0(t2) + .endif + + /* Stop monitoring */ + ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE t0 t1 + fence + 1: +#endif +.endm + +/** + * STACK_GUARD_POST_SWITCH + * Restores or applies new bounds after switching stacks, then restarts monitoring. + * + * Args: + * op_reg – saved monitoring state from PRE_SWITCH + * to_restore – 1=restore from memory, 0=set static bounds + * sp_min – saved bound (restore) or static lower bound (S-mode) + * sp_max – saved bound (restore) or static upper bound (S-mode) + * + * Clobbers: t0, t1, t2 + */ +.macro STACK_GUARD_POST_SWITCH op_reg, to_restore, sp_min, sp_max +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + /* Check if monitoring was enabled (using saved state from op_reg) */ + beqz \op_reg, 1f + + .if \to_restore + /* Restore saved REE/U-mode bounds from memory */ + la t2, \sp_min + lw t0, 0(t2) + la t2, \sp_max + lw t1, 0(t2) + .else + /* Use new TEE/S-mode stack bounds (static symbols) */ + la t0, \sp_min + la t1, \sp_max + .endif + + /* Apply bounds to hardware stack guard */ + ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE t2 t0 t1 + /* Restart monitoring */ + ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE t0 t1 + 1: +#endif +.endm diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S index 5a5e266e189..bf64ea045d5 100644 --- a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S @@ -16,15 +16,10 @@ #include "esp_tee_intr_defs.h" #include "sdkconfig.h" -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD -#include "esp_private/hw_stack_guard.h" -#endif +#include "esp_tee_asm_utils.inc" - .equ SAVE_REGS, 32 - .equ CONTEXT_SIZE, (SAVE_REGS * 4) .equ panic_from_exception, tee_panic_from_exc .equ panic_from_isr, tee_panic_from_isr - .equ MAGIC, 0x1f .equ RTNVAL, 0xc0de .equ ECALL_U_MODE, 0x8 .equ ECALL_M_MODE, 0xb @@ -60,205 +55,6 @@ _ns_sp_min: _ns_sp_max: .word 0 -/** - * STACK_GUARD_PRE_SWITCH - * Stops HW stack-guard monitoring and optionally saves current bounds. - * - * Args: - * op_reg – output register for “monitoring enabled” state (must be reused) - * to_save – 1=save bounds to memory, 0=skip saving - * sp_min – symbol to store lower bound (if to_save=1) - * sp_max – symbol to store upper bound (if to_save=1) - * - * Clobbers: t0, t1, t2, op_reg - */ -.macro STACK_GUARD_PRE_SWITCH op_reg, to_save, sp_min, sp_max -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD - /* Query if monitoring is enabled: result goes into \op_reg */ - ESP_HW_STACK_GUARD_MONITOR_QUERY_CUR_CORE t2 \op_reg - beqz \op_reg, 1f - - .if \to_save - /* Save current REE/U-mode stack bounds */ - ESP_HW_STACK_GUARD_GET_BOUNDS_CUR_CORE t2 t0 t1 - la t2, \sp_min - sw t0, 0(t2) - la t2, \sp_max - sw t1, 0(t2) - .endif - - /* Stop monitoring */ - ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE t0 t1 - fence -1: -#endif -.endm - -/** - * STACK_GUARD_POST_SWITCH - * Restores or applies new bounds after switching stacks, then restarts monitoring. - * - * Args: - * op_reg – saved monitoring state from PRE_SWITCH - * to_restore – 1=restore from memory, 0=set static bounds - * sp_min – saved bound (restore) or static lower bound (S-mode) - * sp_max – saved bound (restore) or static upper bound (S-mode) - * - * Clobbers: t0, t1, t2 - */ -.macro STACK_GUARD_POST_SWITCH op_reg, to_restore, sp_min, sp_max -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD - /* Check if monitoring was enabled (using saved state from op_reg) */ - beqz \op_reg, 1f - - .if \to_restore - /* Restore saved REE/U-mode bounds from memory */ - la t2, \sp_min - lw t0, 0(t2) - la t2, \sp_max - lw t1, 0(t2) - .else - /* Use new TEE/S-mode stack bounds (static symbols) */ - la t0, \sp_min - la t1, \sp_max - .endif - - /* Apply bounds to hardware stack guard */ - ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE t2 t0 t1 - /* Restart monitoring */ - ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE t0 t1 -1: -#endif -.endm - -/* Macro which first allocates space on the stack to save general - * purpose registers, and then save them. GP register is excluded. - * The default size allocated on the stack is CONTEXT_SIZE, but it - * can be overridden. */ -.macro save_general_regs cxt_size=CONTEXT_SIZE - addi sp, sp, -\cxt_size - sw ra, RV_STK_RA(sp) - sw tp, RV_STK_TP(sp) - sw t0, RV_STK_T0(sp) - sw t1, RV_STK_T1(sp) - sw t2, RV_STK_T2(sp) - sw s0, RV_STK_S0(sp) - sw s1, RV_STK_S1(sp) - sw a0, RV_STK_A0(sp) - sw a1, RV_STK_A1(sp) - sw a2, RV_STK_A2(sp) - sw a3, RV_STK_A3(sp) - sw a4, RV_STK_A4(sp) - sw a5, RV_STK_A5(sp) - sw a6, RV_STK_A6(sp) - sw a7, RV_STK_A7(sp) - sw s2, RV_STK_S2(sp) - sw s3, RV_STK_S3(sp) - sw s4, RV_STK_S4(sp) - sw s5, RV_STK_S5(sp) - sw s6, RV_STK_S6(sp) - sw s7, RV_STK_S7(sp) - sw s8, RV_STK_S8(sp) - sw s9, RV_STK_S9(sp) - sw s10, RV_STK_S10(sp) - sw s11, RV_STK_S11(sp) - sw t3, RV_STK_T3(sp) - sw t4, RV_STK_T4(sp) - sw t5, RV_STK_T5(sp) - sw t6, RV_STK_T6(sp) -.endm - -.macro save_mepc - csrr t0, mepc - sw t0, RV_STK_MEPC(sp) -.endm - -.macro save_mcsr - csrr t0, mstatus - sw t0, RV_STK_MSTATUS(sp) - csrr t0, mtvec - sw t0, RV_STK_MTVEC(sp) - csrr t0, mtval - sw t0, RV_STK_MTVAL(sp) - csrr t0, mhartid - sw t0, RV_STK_MHARTID(sp) - csrr t0, mcause - sw t0, RV_STK_MCAUSE(sp) -.endm - -/* Restore the general purpose registers (excluding gp) from the context on - * the stack. The context is then deallocated. The default size is CONTEXT_SIZE - * but it can be overridden. */ -.macro restore_general_regs cxt_size=CONTEXT_SIZE - lw ra, RV_STK_RA(sp) - lw tp, RV_STK_TP(sp) - lw t0, RV_STK_T0(sp) - lw t1, RV_STK_T1(sp) - lw t2, RV_STK_T2(sp) - lw s0, RV_STK_S0(sp) - lw s1, RV_STK_S1(sp) - lw a0, RV_STK_A0(sp) - lw a1, RV_STK_A1(sp) - lw a2, RV_STK_A2(sp) - lw a3, RV_STK_A3(sp) - lw a4, RV_STK_A4(sp) - lw a5, RV_STK_A5(sp) - lw a6, RV_STK_A6(sp) - lw a7, RV_STK_A7(sp) - lw s2, RV_STK_S2(sp) - lw s3, RV_STK_S3(sp) - lw s4, RV_STK_S4(sp) - lw s5, RV_STK_S5(sp) - lw s6, RV_STK_S6(sp) - lw s7, RV_STK_S7(sp) - lw s8, RV_STK_S8(sp) - lw s9, RV_STK_S9(sp) - lw s10, RV_STK_S10(sp) - lw s11, RV_STK_S11(sp) - lw t3, RV_STK_T3(sp) - lw t4, RV_STK_T4(sp) - lw t5, RV_STK_T5(sp) - lw t6, RV_STK_T6(sp) - addi sp,sp, \cxt_size -.endm - -.macro restore_mepc - lw t0, RV_STK_MEPC(sp) - csrw mepc, t0 -.endm - -.macro store_magic_general_regs - lui ra, MAGIC - lui tp, MAGIC - lui t0, MAGIC - lui t1, MAGIC - lui t2, MAGIC - lui s0, MAGIC - lui s1, MAGIC - lui a0, MAGIC - lui a1, MAGIC - lui a2, MAGIC - lui a3, MAGIC - lui a4, MAGIC - lui a5, MAGIC - lui a6, MAGIC - lui a7, MAGIC - lui s2, MAGIC - lui s3, MAGIC - lui s4, MAGIC - lui s5, MAGIC - lui s6, MAGIC - lui s7, MAGIC - lui s8, MAGIC - lui s9, MAGIC - lui s10, MAGIC - lui s11, MAGIC - lui t3, MAGIC - lui t4, MAGIC - lui t5, MAGIC - lui t6, MAGIC -.endm - .section .exception_vectors.text, "ax" /* Exception handler. */ @@ -394,13 +190,14 @@ _skip_thresh_restore: STACK_GUARD_POST_SWITCH t3 1 _ns_sp_min _ns_sp_max fence - call syscall_exit_tee - /* Backup the A0 register * This point is reached after an ecall is triggered after executing the secure service. * The A0 register contains the return value of the corresponding service. * After restoring the entire register context, we assign A0 the value back to the return value. */ csrw mscratch, a0 + + call syscall_exit_tee + restore_general_regs csrrw a0, mscratch, zero diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S index 52d4728dfaa..1274e5df3d6 100644 --- a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S @@ -16,15 +16,10 @@ #include "esp_tee_intr_defs.h" #include "sdkconfig.h" -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD -#include "esp_private/hw_stack_guard.h" -#endif +#include "esp_tee_asm_utils.inc" - .equ SAVE_REGS, 32 - .equ CONTEXT_SIZE, (SAVE_REGS * 4) .equ panic_from_exception, tee_panic_from_exc .equ panic_from_isr, tee_panic_from_isr - .equ MAGIC, 0x1f .equ RTNVAL, 0xc0de .equ ECALL_U_MODE, 0x8 .equ ECALL_M_MODE, 0xb @@ -65,205 +60,6 @@ _ns_sp_min: _ns_sp_max: .word 0 -/** - * STACK_GUARD_PRE_SWITCH - * Stops HW stack-guard monitoring and optionally saves current bounds. - * - * Args: - * op_reg – output register for “monitoring enabled” state (must be reused) - * to_save – 1=save bounds to memory, 0=skip saving - * sp_min – symbol to store lower bound (if to_save=1) - * sp_max – symbol to store upper bound (if to_save=1) - * - * Clobbers: t0, t1, t2, op_reg - */ -.macro STACK_GUARD_PRE_SWITCH op_reg, to_save, sp_min, sp_max -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD - /* Query if monitoring is enabled: result goes into \op_reg */ - ESP_HW_STACK_GUARD_MONITOR_QUERY_CUR_CORE t2 \op_reg - beqz \op_reg, 1f - - .if \to_save - /* Save current REE/U-mode stack bounds */ - ESP_HW_STACK_GUARD_GET_BOUNDS_CUR_CORE t2 t0 t1 - la t2, \sp_min - sw t0, 0(t2) - la t2, \sp_max - sw t1, 0(t2) - .endif - - /* Stop monitoring */ - ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE t0 t1 - fence -1: -#endif -.endm - -/** - * STACK_GUARD_POST_SWITCH - * Restores or applies new bounds after switching stacks, then restarts monitoring. - * - * Args: - * op_reg – saved monitoring state from PRE_SWITCH - * to_restore – 1=restore from memory, 0=set static bounds - * sp_min – saved bound (restore) or static lower bound (S-mode) - * sp_max – saved bound (restore) or static upper bound (S-mode) - * - * Clobbers: t0, t1, t2 - */ -.macro STACK_GUARD_POST_SWITCH op_reg, to_restore, sp_min, sp_max -#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD - /* Check if monitoring was enabled (using saved state from op_reg) */ - beqz \op_reg, 1f - - .if \to_restore - /* Restore saved REE/U-mode bounds from memory */ - la t2, \sp_min - lw t0, 0(t2) - la t2, \sp_max - lw t1, 0(t2) - .else - /* Use new TEE/S-mode stack bounds (static symbols) */ - la t0, \sp_min - la t1, \sp_max - .endif - - /* Apply bounds to hardware stack guard */ - ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE t2 t0 t1 - /* Restart monitoring */ - ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE t0 t1 -1: -#endif -.endm - -/* Macro which first allocates space on the stack to save general - * purpose registers, and then save them. GP register is excluded. - * The default size allocated on the stack is CONTEXT_SIZE, but it - * can be overridden. */ -.macro save_general_regs cxt_size=CONTEXT_SIZE - addi sp, sp, -\cxt_size - sw ra, RV_STK_RA(sp) - sw tp, RV_STK_TP(sp) - sw t0, RV_STK_T0(sp) - sw t1, RV_STK_T1(sp) - sw t2, RV_STK_T2(sp) - sw s0, RV_STK_S0(sp) - sw s1, RV_STK_S1(sp) - sw a0, RV_STK_A0(sp) - sw a1, RV_STK_A1(sp) - sw a2, RV_STK_A2(sp) - sw a3, RV_STK_A3(sp) - sw a4, RV_STK_A4(sp) - sw a5, RV_STK_A5(sp) - sw a6, RV_STK_A6(sp) - sw a7, RV_STK_A7(sp) - sw s2, RV_STK_S2(sp) - sw s3, RV_STK_S3(sp) - sw s4, RV_STK_S4(sp) - sw s5, RV_STK_S5(sp) - sw s6, RV_STK_S6(sp) - sw s7, RV_STK_S7(sp) - sw s8, RV_STK_S8(sp) - sw s9, RV_STK_S9(sp) - sw s10, RV_STK_S10(sp) - sw s11, RV_STK_S11(sp) - sw t3, RV_STK_T3(sp) - sw t4, RV_STK_T4(sp) - sw t5, RV_STK_T5(sp) - sw t6, RV_STK_T6(sp) -.endm - -.macro save_mepc - csrr t0, mepc - sw t0, RV_STK_MEPC(sp) -.endm - -.macro save_mcsr - csrr t0, mstatus - sw t0, RV_STK_MSTATUS(sp) - csrr t0, mtvec - sw t0, RV_STK_MTVEC(sp) - csrr t0, mtval - sw t0, RV_STK_MTVAL(sp) - csrr t0, mhartid - sw t0, RV_STK_MHARTID(sp) - csrr t0, mcause - sw t0, RV_STK_MCAUSE(sp) -.endm - -/* Restore the general purpose registers (excluding gp) from the context on - * the stack. The context is then deallocated. The default size is CONTEXT_SIZE - * but it can be overridden. */ -.macro restore_general_regs cxt_size=CONTEXT_SIZE - lw ra, RV_STK_RA(sp) - lw tp, RV_STK_TP(sp) - lw t0, RV_STK_T0(sp) - lw t1, RV_STK_T1(sp) - lw t2, RV_STK_T2(sp) - lw s0, RV_STK_S0(sp) - lw s1, RV_STK_S1(sp) - lw a0, RV_STK_A0(sp) - lw a1, RV_STK_A1(sp) - lw a2, RV_STK_A2(sp) - lw a3, RV_STK_A3(sp) - lw a4, RV_STK_A4(sp) - lw a5, RV_STK_A5(sp) - lw a6, RV_STK_A6(sp) - lw a7, RV_STK_A7(sp) - lw s2, RV_STK_S2(sp) - lw s3, RV_STK_S3(sp) - lw s4, RV_STK_S4(sp) - lw s5, RV_STK_S5(sp) - lw s6, RV_STK_S6(sp) - lw s7, RV_STK_S7(sp) - lw s8, RV_STK_S8(sp) - lw s9, RV_STK_S9(sp) - lw s10, RV_STK_S10(sp) - lw s11, RV_STK_S11(sp) - lw t3, RV_STK_T3(sp) - lw t4, RV_STK_T4(sp) - lw t5, RV_STK_T5(sp) - lw t6, RV_STK_T6(sp) - addi sp,sp, \cxt_size -.endm - -.macro restore_mepc - lw t0, RV_STK_MEPC(sp) - csrw mepc, t0 -.endm - -.macro store_magic_general_regs - lui ra, MAGIC - lui tp, MAGIC - lui t0, MAGIC - lui t1, MAGIC - lui t2, MAGIC - lui s0, MAGIC - lui s1, MAGIC - lui a0, MAGIC - lui a1, MAGIC - lui a2, MAGIC - lui a3, MAGIC - lui a4, MAGIC - lui a5, MAGIC - lui a6, MAGIC - lui a7, MAGIC - lui s2, MAGIC - lui s3, MAGIC - lui s4, MAGIC - lui s5, MAGIC - lui s6, MAGIC - lui s7, MAGIC - lui s8, MAGIC - lui s9, MAGIC - lui s10, MAGIC - lui s11, MAGIC - lui t3, MAGIC - lui t4, MAGIC - lui t5, MAGIC - lui t6, MAGIC -.endm - .section .exception_vectors.text, "ax" /* Exception handler. */ @@ -386,13 +182,14 @@ _skip_thresh_restore: STACK_GUARD_POST_SWITCH t3 1 _ns_sp_min _ns_sp_max fence - call syscall_exit_tee - /* Backup the A0 register * This point is reached after an ecall is triggered after executing the secure service. * The A0 register contains the return value of the corresponding service. * After restoring the entire register context, we assign A0 the value back to the return value. */ csrw mscratch, a0 + + call syscall_exit_tee + restore_general_regs csrrw a0, mscratch, zero diff --git a/components/esp_tee/test_apps/.build-test-rules.yml b/components/esp_tee/test_apps/.build-test-rules.yml index 081d926e83a..b64c2f89e47 100644 --- a/components/esp_tee/test_apps/.build-test-rules.yml +++ b/components/esp_tee/test_apps/.build-test-rules.yml @@ -4,6 +4,8 @@ components/esp_tee/test_apps/tee_cli_app: disable: - if: IDF_TARGET not in ["esp32c6", "esp32c5", "esp32c61"] reason: only supported with c6, c5 and c61 + depends_components: + - esp_tee components/esp_tee/test_apps/tee_test_fw: disable: diff --git a/components/esp_tee/test_apps/tee_cli_app/README.md b/components/esp_tee/test_apps/tee_cli_app/README.md index 21e76c7d67d..9768291f558 100644 --- a/components/esp_tee/test_apps/tee_cli_app/README.md +++ b/components/esp_tee/test_apps/tee_cli_app/README.md @@ -138,9 +138,9 @@ help [] [-v <0|1>] ```log esp32c6> tee_att_info -I (8180) tee_attest: Attestation token - Length: 1587 +I (8180) tee_attest: Attestation token - Length: 1705 I (8180) tee_attest: Attestation token - Data: -'{"header":{"magic":"44fef7cc","encr_alg":"","sign_alg":"ecdsa_secp256r1_sha256","key_id":"tee_att_key0"},"eat":{"auth_challenge":"dcb9b53143ad6b081dad1a05c7ebda4e314d388762215799cf24ed52e9387678","client_id":262974944,"device_ver":0,"device_id":"cd9c173cb3675c7adfae243f0cd9841e4bce003237cb5321927a85a86cb4b32e","instance_id":"9616ef0ecf02cdc89a3749f8fc16b3103d5100bd42d9312fcd04593baa7bac64","psa_cert_ref":"0716053550477-10100","device_status":165,"sw_claims":{"tee":{"type":1,"ver":"v0.3.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"94536998e1dcb2a036477cb2feb01ed4fff67ba6208f30482346c62bca64b280","digest_validated":true,"sign_verified":true}},"app":{"type":2,"ver":"v0.1.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"3d4c038fcec76852b4d07acb9e94afaf5fca69fc2eb212a32032d09ce5b4f2b3","digest_validated":true,"sign_verified":true,"secure_padding":true}},"bootloader":{"type":0,"ver":"","idf_ver":"","secure_ver":-1,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"1bef421beb1a4642c6fcefb3e37fd4afad60cb4074e538f42605b012c482b946","digest_validated":true,"sign_verified":true}}}},"public_key":{"compressed":"02039c4bfab0762af1aff2fe5596b037f629cf839da8c4a9c0018afedfccf519a6"},"sign":{"r":"915e749f5a780bc21a2b21821cfeb54286dc742e9f12f2387e3de9b8b1a70bc9","s":"1e583236f2630b0fe8e291645ffa35d429f14035182e19868508d4dac0e1a441"}}' +'{"header":{"magic":"44fef7cc","encr_alg":"","sign_alg":"ecdsa_secp256r1_sha256","key_id":"tee_att_key0"},"eat":{"auth_challenge":"dcb9b53143ad6b081dad1a05c7ebda4e314d388762215799cf24ed52e9387678","client_id":262974944,"chip_id":13,"device_ver":0,"ueid":{"mac":"d885ac67c978","optional_id":"94fa4d7e305682714d48e7bbd710c961"},"device_id":"cd9c173cb3675c7adfae243f0cd9841e4bce003237cb5321927a85a86cb4b32e","instance_id":"9616ef0ecf02cdc89a3749f8fc16b3103d5100bd42d9312fcd04593baa7bac64","psa_cert_ref":"0716053550477-10100","device_status":165,"sw_claims":{"tee":{"type":1,"ver":"v0.3.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"94536998e1dcb2a036477cb2feb01ed4fff67ba6208f30482346c62bca64b280","digest_validated":true,"sign_verified":true}},"app":{"type":2,"ver":"v0.1.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"3d4c038fcec76852b4d07acb9e94afaf5fca69fc2eb212a32032d09ce5b4f2b3","digest_validated":true,"sign_verified":true,"secure_padding":true}},"bootloader":{"type":0,"ver":"","idf_ver":"","secure_ver":-1,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"1bef421beb1a4642c6fcefb3e37fd4afad60cb4074e538f42605b012c482b946","digest_validated":true,"sign_verified":true}}}},"public_key":{"compressed":"02039c4bfab0762af1aff2fe5596b037f629cf839da8c4a9c0018afedfccf519a6"},"sign":{"r":"915e749f5a780bc21a2b21821cfeb54286dc742e9f12f2387e3de9b8b1a70bc9","s":"1e583236f2630b0fe8e291645ffa35d429f14035182e19868508d4dac0e1a441"}}' ``` diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults index c35d9943e4b..a0ae715a92c 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults @@ -20,3 +20,6 @@ CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=30000 CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="test_certs/server_cert.pem" + +# Takes effect only when Secure boot is enabled +CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT=y diff --git a/components/esp_tee/test_apps/tee_cli_app/test_keys/secure_boot_signing_key.pem b/components/esp_tee/test_apps/tee_cli_app/test_keys/secure_boot_signing_key_rsa_3072.pem similarity index 100% rename from components/esp_tee/test_apps/tee_cli_app/test_keys/secure_boot_signing_key.pem rename to components/esp_tee/test_apps/tee_cli_app/test_keys/secure_boot_signing_key_rsa_3072.pem diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml index f0adf8dcad1..c7f37bba749 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml @@ -77,3 +77,7 @@ secure_services: type: custom function: esp_tee_test_stack_underflow args: 0 + - id: 219 + type: custom + function: esp_tee_test_read_sec_stg + args: 1 diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c index 6978a657803..0547c79d54c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c @@ -1,13 +1,21 @@ /* - * 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 + #include "esp_cpu.h" +#include "esp_err.h" #include "esp_log.h" #include "esp_tee.h" +#include "esp_tee_flash.h" +#include "esp_tee_memory_utils.h" #include "esp_tee_test.h" #include "esp_attr.h" +#include "esp_flash_partitions.h" + static const char *TAG = "test_sec_srv"; /* Sample Trusted App */ @@ -54,3 +62,23 @@ uint32_t _ss_esp_tee_test_priv_mode_switch(uint32_t *a, uint32_t *b) return c; } + +esp_err_t _ss_esp_tee_test_read_sec_stg(uint8_t *buf) +{ + if (!esp_tee_buf_in_ree(buf, FLASH_SECTOR_SIZE)) { + return ESP_ERR_INVALID_ARG; + } + + esp_partition_info_t pinfo; + esp_err_t err = esp_tee_flash_find_partition(PART_TYPE_DATA, PART_SUBTYPE_DATA_WIFI, + ESP_TEE_SEC_STG_PART_LABEL, &pinfo); + if (err != ESP_OK) { + return err; + } + + if (pinfo.pos.size < FLASH_SECTOR_SIZE) { + return ESP_ERR_INVALID_SIZE; + } + + return (esp_err_t)esp_tee_flash_read(pinfo.pos.offset, (uint32_t *)buf, FLASH_SECTOR_SIZE, false); +} diff --git a/components/esp_tee/test_apps/tee_test_fw/conftest.py b/components/esp_tee/test_apps/tee_test_fw/conftest.py index 66cdddb7d61..b025bc4db43 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -4,6 +4,7 @@ import base64 import csv import os +import re import shutil import subprocess import sys @@ -202,25 +203,6 @@ class TEESerial(IdfSerial): def _get_flash_size(self) -> Any: return self.app.sdkconfig.get('ESPTOOLPY_FLASHSIZE', '') - @EspSerial.use_esptool() - def bootloader_force_flash_if_req(self) -> None: - # Forcefully flash the bootloader only if security features are enabled - if any( - ( - self.app.sdkconfig.get('SECURE_BOOT', True), - self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True), - ) - ): - offs = int(self.app.sdkconfig.get('BOOTLOADER_OFFSET_IN_FLASH', 0)) - bootloader_path = os.path.join(self.app.binary_path, 'bootloader', 'bootloader.bin') - encrypt = '--encrypt' if self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED') else '' - flash_size = self._get_flash_size() - - esptool.main( - f'--no-stub write-flash {offs} {bootloader_path} --force {encrypt} --flash-size {flash_size}'.split(), - esp=self.esp, - ) - @EspSerial.use_esptool() def custom_erase_partition(self, partition: str) -> None: if self.app.sdkconfig.get('SECURE_ENABLE_SECURE_ROM_DL_MODE'): @@ -294,29 +276,133 @@ class TEESerial(IdfSerial): if os.path.exists(file): os.remove(file) - @EspSerial.use_esptool() - def custom_flash(self) -> None: - self.bootloader_force_flash_if_req() - self.flash() - @EspSerial.use_esptool() def custom_flash_w_test_tee_img_gen(self) -> None: - self.bootloader_force_flash_if_req() self.flash() self.copy_test_tee_img('ota_1', False) @EspSerial.use_esptool() def custom_flash_w_test_tee_img_rb(self) -> None: - self.bootloader_force_flash_if_req() self.flash() self.copy_test_tee_img('ota_1', True) @EspSerial.use_esptool() def custom_flash_with_empty_sec_stg(self) -> None: - self.bootloader_force_flash_if_req() self.flash() self.custom_erase_partition('secure_storage') + KEY_DEFS_ENCRYPTION_TEST: list[str] = [ + 'aes256_key0', + 'aes256_key1', + 'attest_key', + 'ecdsa_p256_key0', + ] + + # TEE Secure Storage Development mode + # NVS XTS-AES keys: E-key=0x33*32 || T-key=0xCC*32 + NVS_KEYS_DEV_B64 = 'MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzPMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzA==' + + @property + def nvs_partition_gen(self) -> str: + return str( + Path(os.environ['IDF_PATH']) + / 'components' + / 'nvs_flash' + / 'nvs_partition_generator' + / 'nvs_partition_gen.py' + ) + + def derive_sec_stg_nvs_keys(self, out_path: Path) -> None: + out_path.parent.mkdir(parents=True, exist_ok=True) + if self.app.sdkconfig.get('SECURE_TEE_SEC_STG_MODE_RELEASE'): + hmac_key_src = self.TEST_KEYS_DIR / 'tee_sec_stg_hmac_key.bin' + self.run_command( + [ + sys.executable, + self.nvs_partition_gen, + 'generate-key', + '--key_protect_hmac', + '--kp_hmac_inputkey', + str(hmac_key_src), + '--keyfile', + out_path.name, + '--outdir', + str(out_path.parent), + ] + ) + (out_path.parent / 'keys' / out_path.name).replace(out_path) + else: + self.write_keys_to_file(self.NVS_KEYS_DEV_B64, out_path) + + def decrypt_sec_stg_partition(self, dump_path: Path, keys_path: Path, decrypted_path: Path) -> None: + self.run_command( + [sys.executable, self.nvs_partition_gen, 'decrypt', str(dump_path), str(keys_path), str(decrypted_path)] + ) + + _SEC_STG_HEX_LINE_RE = re.compile( + rb'test_esp_tee_sec_storage:\s+((?:[0-9a-f]{2} ){0,15}[0-9a-f]{2})', + ) + SEC_STG_DUMP_SZ = 4096 + + def capture_sec_stg_partition_dump(self, dut: Any, timeout: float = 60) -> bytes: + dut.expect_exact('SEC_STG_DUMP_BEGIN', timeout=timeout) + blob = dut.expect_exact('SEC_STG_DUMP_END', timeout=timeout, return_what_before_match=True) + + raw = bytearray() + for match in self._SEC_STG_HEX_LINE_RE.finditer(blob): + for tok in match.group(1).split(): + raw.append(int(tok, 16)) + + if len(raw) != self.SEC_STG_DUMP_SZ: + raise RuntimeError( + f'Hex dump parse mismatch: got {len(raw)} bytes, expected {self.SEC_STG_DUMP_SZ}.\n' + f'Blob (first 256 bytes): {blob[:256]!r}' + ) + + # Make sure the Unity case actually passed before we trust the dump. + m = dut.expect(re.compile(rb'(\d+) Tests (\d+) Failures (\d+) Ignored'), timeout=timeout) + if int(m.group(2)) != 0: + raise RuntimeError(f'Unity reported {m.group(2).decode()} failures while running encryption test') + + return bytes(raw) + + def _run_nvs_tool_minimal(self, partition_file: Path) -> subprocess.CompletedProcess: + nvs_tool = Path(os.environ['IDF_PATH']) / 'components' / 'nvs_flash' / 'nvs_partition_tool' / 'nvs_tool.py' + return subprocess.run( + [sys.executable, str(nvs_tool), '-d', 'minimal', '--color', 'never', str(partition_file)], + capture_output=True, + text=True, + ) + + def verify_tee_sec_stg_encryption(self, dut: Any) -> None: + tmp_dir = self.TMP_DIR / 'sec_stg_encryption' + tmp_dir.mkdir(parents=True, exist_ok=True) + raw_path = tmp_dir / 'tee_sec_stg_dump.bin' + keys_path = tmp_dir / self.NVS_KEYS_FILE + decrypted_path = tmp_dir / 'tee_sec_stg_decr.bin' + expected_key_ids = self.KEY_DEFS_ENCRYPTION_TEST + + print('Verifying TEE Secure Storage NVS partition encryption (XTS-AES-512: 256-bit AES, 512-bit total key)') + try: + raw_bytes = self.capture_sec_stg_partition_dump(dut) + raw_path.write_bytes(raw_bytes) + + self.derive_sec_stg_nvs_keys(keys_path) + self.decrypt_sec_stg_partition(raw_path, keys_path, decrypted_path) + + print('Confirming key IDs are NOT present in the raw (encrypted) NVS dump') + raw_parse = self._run_nvs_tool_minimal(raw_path) + for key_id in expected_key_ids: + assert key_id not in raw_parse.stdout, f'{key_id!r} surfaced in raw dump (not encrypted)' + + print('Confirming key IDs ARE present after XTS-AES decrypt with the derived NVS keys') + decrypted_parse = self._run_nvs_tool_minimal(decrypted_path) + assert decrypted_parse.returncode == 0, f'nvs_tool exit {decrypted_parse.returncode} on decrypted dump' + for key_id in expected_key_ids: + assert key_id in decrypted_parse.stdout, f'{key_id!r} missing after decrypt (wrong XTS-AES key?)' + finally: + shutil.rmtree(tmp_dir, ignore_errors=True) + KEY_DEFS: list[dict[str, Any]] = [ {'key': 'aes256_key0', 'type': 'aes256', 'input': None, 'write_once': True}, { @@ -354,12 +440,11 @@ class TEESerial(IdfSerial): }, ] - NVS_KEYS_B64 = 'MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzPMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzA==' - + TEST_KEYS_DIR = Path(__file__).parent / 'test_keys' TMP_DIR = Path('tmp') - NVS_KEYS_PATH = TMP_DIR / 'nvs_keys.bin' NVS_CSV_PATH = TMP_DIR / 'tee_sec_stg_val.csv' NVS_BIN_PATH = TMP_DIR / 'tee_sec_stg_nvs.bin' + NVS_KEYS_FILE = 'tee_sec_stg_nvs_keys.bin' def run_command(self, command: list[str]) -> None: try: @@ -391,16 +476,19 @@ class TEESerial(IdfSerial): input_path = tmp_dir / entry['input'] self.write_keys_to_file(entry['b64'], input_path) entry['input'] = str(input_path) - self.write_keys_to_file(self.NVS_KEYS_B64, self.NVS_KEYS_PATH) - idf_path = Path(os.environ['IDF_PATH']) ESP_TEE_SEC_STG_KEYGEN = os.path.join( - idf_path, 'components', 'esp_tee', 'scripts', 'esp_tee_sec_stg_keygen', 'esp_tee_sec_stg_keygen.py' - ) - NVS_PARTITION_GEN = os.path.join( - idf_path, 'components', 'nvs_flash', 'nvs_partition_generator', 'nvs_partition_gen.py' + os.environ['IDF_PATH'], + 'components', + 'esp_tee', + 'scripts', + 'esp_tee_sec_stg_keygen', + 'esp_tee_sec_stg_keygen.py', ) + nvs_keys = tmp_dir / self.NVS_KEYS_FILE + self.derive_sec_stg_nvs_keys(nvs_keys) + cmds = [ [sys.executable, ESP_TEE_SEC_STG_KEYGEN, '-k', entry['type'], '-o', str(tmp_dir / f'{entry["key"]}.bin')] + (['-i', entry['input']] if entry['input'] else []) @@ -410,13 +498,12 @@ class TEESerial(IdfSerial): csv_path = self.create_tee_sec_stg_csv(tmp_dir) nvs_bin = self.NVS_BIN_PATH - nvs_keys = self.NVS_KEYS_PATH size = self.app.partition_table['secure_storage']['size'] cmds.append( [ sys.executable, - NVS_PARTITION_GEN, + self.nvs_partition_gen, 'encrypt', str(csv_path), str(nvs_bin), @@ -430,10 +517,9 @@ class TEESerial(IdfSerial): for cmd in cmds: self.run_command(cmd) - self.bootloader_force_flash_if_req() self.flash() self.custom_erase_partition('secure_storage') - self.custom_write_partition('secure_storage', nvs_bin) + self.custom_write_partition('secure_storage', str(nvs_bin)) finally: shutil.rmtree(tmp_dir) diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ota.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ota.c index 6096e49ac3e..5e305af3839 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ota.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ota.c @@ -127,8 +127,8 @@ TEST_CASE("Test TEE OTA - Corrupted image", "[ota_neg_2]") /* Corrupting the image */ ESP_LOGI(TAG, "Corrupting the image at some offset..."); uint32_t corrupt[8] = {[0 ... 7] = 0x0BADC0DE}; - curr_write_offset -= (2 * FLASH_SECTOR_SIZE + sizeof(corrupt)); - TEST_ESP_OK(esp_tee_ota_write(curr_write_offset, (const void *)corrupt, sizeof(corrupt))); + uint32_t offs = SOC_MMU_PAGE_SIZE + 0x200; + TEST_ESP_OK(esp_tee_ota_write(offs, (const void *)corrupt, sizeof(corrupt))); TEST_ESP_ERR(ESP_ERR_IMAGE_INVALID, esp_tee_ota_end()); } diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c index 06860307328..c5ea5f79781 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include "esp_log.h" @@ -364,6 +365,45 @@ TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storag TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } +TEST_CASE("Test TEE Secure Storage - Verify data encryption", "[sec_storage_encr]") +{ + ESP_LOGI(TAG, "Populating NVS-based TEE Secure Storage; encrypted with XTS-AES-512"); + static const struct { + const char *id; + esp_tee_sec_storage_type_t type; + uint32_t flags; + } key_cfgs[] = { + { "aes256_key0", ESP_SEC_STG_KEY_AES256, SEC_STORAGE_FLAG_WRITE_ONCE }, + { "aes256_key1", ESP_SEC_STG_KEY_AES256, SEC_STORAGE_FLAG_NONE }, + { "attest_key", ESP_SEC_STG_KEY_ECDSA_SECP256R1, SEC_STORAGE_FLAG_WRITE_ONCE }, + { "ecdsa_p256_key0", ESP_SEC_STG_KEY_ECDSA_SECP256R1, SEC_STORAGE_FLAG_NONE }, + }; + + for (size_t i = 0; i < sizeof(key_cfgs) / sizeof(key_cfgs[0]); i++) { + esp_tee_sec_storage_key_cfg_t cfg = { + .id = key_cfgs[i].id, + .type = key_cfgs[i].type, + .flags = key_cfgs[i].flags, + }; + if ((cfg.flags & SEC_STORAGE_FLAG_WRITE_ONCE) == 0) { + esp_err_t err = esp_tee_sec_storage_clear_key(cfg.id); + TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND); + } + TEST_ESP_OK(esp_tee_sec_storage_gen_key(&cfg)); + } + + const size_t dump_sz = 4096; + uint8_t *buf = heap_caps_malloc(dump_sz, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + + TEST_ESP_OK((esp_err_t)esp_tee_service_call(2, SS_ESP_TEE_TEST_READ_SEC_STG, buf)); + printf("\nSEC_STG_DUMP_BEGIN\n"); + ESP_LOG_BUFFER_HEX(TAG, buf, dump_sz); + printf("SEC_STG_DUMP_END\n"); + + free(buf); +} + TEST_CASE("Test TEE Secure Storage - WRITE_ONCE keys", "[sec_storage]") { const char *key_id = "key_id_test_wo"; @@ -425,6 +465,10 @@ static void do_ecdsa_sign_and_verify(const esp_tee_sec_storage_key_cfg_t *cfg, c TEST_ESP_OK(verify_ecdsa_sign(cfg->type, digest, digest_len, &pubkey, &sign)); } +/* NOTE: In release mode (CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE), the test expects + * the eFuse-burned HMAC key used for TEE secure storage to be available at + * the path "test_keys/tee_sec_stg_hmac_key.bin" + */ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_keygen]") { const char *aes_key_ids[] = { "aes256_key0", "aes256_key1" }; diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index 73590e48d2a..791bc61d1cd 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -6,7 +6,7 @@ from enum import Enum import pytest from pytest_embedded_idf import IdfDut from pytest_embedded_idf.utils import idf_parametrize -from tee_exception_cfg import TEE_EXCEPTION_TEST_MAP +from tee_exception_test_map import TEE_EXCEPTION_TEST_MAP # ---------------- Pytest build parameters ---------------- @@ -20,6 +20,12 @@ CONFIG_DEFAULT = [ ] CONFIG_OTA = [ + # 'config, target, markers', + ('tee_ota', target, (pytest.mark.generic,)) + for target in TESTING_TARGETS +] + +CONFIG_OTA_NO_AUTOFLASH = [ # 'config, target, skip_autoflash, markers', ('tee_ota', target, 'y', (pytest.mark.generic,)) for target in TESTING_TARGETS @@ -50,8 +56,10 @@ def test_esp_tee(dut: IdfDut) -> None: CONFIG_ALL, indirect=['config', 'target'], ) -@pytest.mark.skipif(targets=['esp32c61'], reason='Not supported') def test_esp_tee_crypto_aes(dut: IdfDut) -> None: + if dut.target == 'esp32c61': + pytest.skip(f'AES not supported on {dut.target}') + dut.run_all_single_board_cases(group='aes') dut.run_all_single_board_cases(group='aes-gcm') @@ -72,8 +80,10 @@ def test_esp_tee_crypto_sha(dut: IdfDut) -> None: CONFIG_ALL, indirect=['config', 'target'], ) -@pytest.mark.skipif(targets=['esp32c61'], reason='Not supported') def test_esp_tee_aes_perf(dut: IdfDut) -> None: + if dut.target == 'esp32c61': + pytest.skip(f'AES not supported on {dut.target}') + for i in range(10): dut.run_all_single_board_cases(name=['mbedtls AES performance']) @@ -121,6 +131,13 @@ def test_esp_tee_isolation_checks(dut: IdfDut) -> None: for test_name, expected in cfg.items(): run_exception_case(dut, 'Test REE-TEE isolation', test_name, expected, check_origin=True) + # ESP32-C61: MMU-spillover gracefully reboots instead of panicking + if dut.target == 'esp32c61': + dut.skip_decode_panic = True + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('"Test REE-TEE isolation: MMU-spillover"') + dut.expect_exact('Failed MMU operation, rebooting!', timeout=10) + @idf_parametrize( 'config, target, markers', @@ -238,8 +255,6 @@ def run_flash_access_test(dut: IdfDut, api: TeeFlashAccessApi, test_name: str) - # Panics are expected during these tests dut.skip_decode_panic = True - dut.serial.custom_flash() - extra_data = dut._parse_test_menu() test_case = next((tc for tc in extra_data if tc.name == test_name), None) @@ -250,9 +265,9 @@ def run_flash_access_test(dut: IdfDut, api: TeeFlashAccessApi, test_name: str) - @idf_parametrize( - 'config, target, skip_autoflash, markers', + 'config, target, markers', CONFIG_OTA, - indirect=['config', 'target', 'skip_autoflash'], + indirect=['config', 'target'], ) def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: run_flash_access_test( @@ -261,9 +276,9 @@ def test_esp_tee_flash_prot_esp_partition_mmap(dut: IdfDut) -> None: @idf_parametrize( - 'config, target, skip_autoflash, markers', + 'config, target, markers', CONFIG_OTA, - indirect=['config', 'target', 'skip_autoflash'], + indirect=['config', 'target'], ) def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: run_flash_access_test( @@ -272,9 +287,9 @@ def test_esp_tee_flash_prot_spi_flash_mmap(dut: IdfDut) -> None: @idf_parametrize( - 'config, target, skip_autoflash, markers', + 'config, target, markers', CONFIG_OTA, - indirect=['config', 'target', 'skip_autoflash'], + indirect=['config', 'target'], ) def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: run_flash_access_test( @@ -283,18 +298,18 @@ def test_esp_tee_flash_prot_esp_rom_spiflash(dut: IdfDut) -> None: @idf_parametrize( - 'config, target, skip_autoflash, markers', + 'config, target, markers', CONFIG_OTA, - indirect=['config', 'target', 'skip_autoflash'], + indirect=['config', 'target'], ) def test_esp_tee_flash_prot_esp_partition(dut: IdfDut) -> None: run_flash_access_test(dut, TeeFlashAccessApi.ESP_PARTITION, 'Test REE-TEE isolation: Flash - SPI1 (esp_partition)') @idf_parametrize( - 'config, target, skip_autoflash, markers', + 'config, target, markers', CONFIG_OTA, - indirect=['config', 'target', 'skip_autoflash'], + indirect=['config', 'target'], ) def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: run_flash_access_test(dut, TeeFlashAccessApi.ESP_FLASH, 'Test REE-TEE isolation: Flash - SPI1 (esp_flash)') @@ -303,9 +318,11 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: # ---------------- TEE Local OTA tests ---------------- -@pytest.mark.generic -@idf_parametrize('config', ['tee_ota'], indirect=['config']) -@idf_parametrize('target', TESTING_TARGETS, indirect=['target']) +@idf_parametrize( + 'config, target, markers', + CONFIG_OTA, + indirect=['config', 'target'], +) def test_esp_tee_ota_negative(dut: IdfDut) -> None: # start test dut.run_all_single_board_cases(group='ota_neg_1', timeout=10) @@ -313,7 +330,7 @@ def test_esp_tee_ota_negative(dut: IdfDut) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_ota_corrupted_img(dut: IdfDut) -> None: @@ -347,7 +364,7 @@ def tee_ota_stage_checks(dut: IdfDut, stage: TeeOtaStage, offset: str) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: @@ -370,7 +387,7 @@ def test_esp_tee_ota_reboot_without_ota_end(dut: IdfDut) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: @@ -401,7 +418,7 @@ def test_esp_tee_ota_valid_img(dut: IdfDut) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_ota_rollback(dut: IdfDut) -> None: @@ -440,7 +457,7 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_secure_storage(dut: IdfDut) -> None: @@ -452,22 +469,43 @@ def test_esp_tee_secure_storage(dut: IdfDut) -> None: @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_secure_storage_with_host_img(dut: IdfDut) -> None: # Flash image and write the secure_storage partition with host-generated keys + + # NOTE: In release mode (CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE), the test + # expects the eFuse-burned HMAC key used for TEE secure storage to be available + # at the path "test_keys/tee_sec_stg_hmac_key.bin" dut.serial.custom_flash_with_host_gen_sec_stg_img() dut.run_all_single_board_cases(group='sec_storage_host_keygen') +@idf_parametrize( + 'config, target, skip_autoflash, markers', + CONFIG_OTA_NO_AUTOFLASH, + indirect=['config', 'target', 'skip_autoflash'], +) +def test_esp_tee_secure_storage_encryption(dut: IdfDut) -> None: + dut.serial.custom_flash_with_empty_sec_stg() + + # NOTE: In release mode (CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE), the test + # expects the eFuse-burned HMAC key used for TEE secure storage to be available + # at the path "test_keys/tee_sec_stg_hmac_key.bin" + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('"Test TEE Secure Storage - Verify data encryption"') + + dut.serial.verify_tee_sec_stg_encryption(dut) + + # ---------------- TEE Attestation tests ---------------- @idf_parametrize( 'config, target, skip_autoflash, markers', - CONFIG_OTA, + CONFIG_OTA_NO_AUTOFLASH, indirect=['config', 'target', 'skip_autoflash'], ) def test_esp_tee_attestation(dut: IdfDut) -> None: diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults index 9abd3154f4c..ad47c1b6908 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -15,3 +15,6 @@ CONFIG_PARTITION_TABLE_OFFSET=0xF000 # Increasing TEE I/DRAM size CONFIG_SECURE_TEE_IRAM_SIZE=0x8800 CONFIG_SECURE_TEE_DRAM_SIZE=0x5800 + +# Takes effect only when Secure boot is enabled +CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT=y diff --git a/components/esp_tee/test_apps/tee_test_fw/tee_exception_test_map.py b/components/esp_tee/test_apps/tee_test_fw/tee_exception_test_map.py index 2527d4df93f..c25fce29110 100644 --- a/components/esp_tee/test_apps/tee_test_fw/tee_exception_test_map.py +++ b/components/esp_tee/test_apps/tee_test_fw/tee_exception_test_map.py @@ -78,6 +78,12 @@ _TARGET_OVERRIDES: dict[str, dict[str, Any]] = { }, }, 'esp32c61': { + # NOTE: On ESP32-C61, MMU-spillover does not raise a CPU panic — the TEE + # test fills the bad mapping with a poison pattern and calls esp_restart(). + # Verified separately in the pytest, so drop it from the panic-driven map. + 'ree_isolation': { + '_remove': ['MMU-spillover'], + }, # NOTE: ESP32-C61 does not support the following peripherals 'apm_violation': { '_remove': ['AES', 'HMAC', 'DS'], diff --git a/components/esp_tee/test_apps/tee_test_fw/test_keys/tee_sec_stg_hmac_key.bin b/components/esp_tee/test_apps/tee_test_fw/test_keys/tee_sec_stg_hmac_key.bin new file mode 100644 index 00000000000..9868f801a9a Binary files /dev/null and b/components/esp_tee/test_apps/tee_test_fw/test_keys/tee_sec_stg_hmac_key.bin differ diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake index 63b771fbe8c..7a69f5a7db3 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake @@ -83,31 +83,29 @@ if(CONFIG_SOC_AES_SUPPORTED) "${COMPONENT_DIR}/port/aes/esp_aes_common.c" "${COMPONENT_DIR}/port/aes/esp_aes_xts.c") target_include_directories(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/include/aes") - if(CONFIG_MBEDTLS_HARDWARE_AES) - target_sources(tfpsacrypto PRIVATE - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c" - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c" - ) - endif() - + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c" + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c" + ) endif() # SHA implementation if(CONFIG_SOC_SHA_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c" - "${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha1.c" "${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha256.c" - "${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha512.c" "${COMPONENT_DIR}/port/sha/core/sha.c" "${COMPONENT_DIR}/port/sha/esp_sha.c" - "${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c" - ) -endif() - -if(CONFIG_MBEDTLS_ROM_MD5) - target_sources(tfpsacrypto PRIVATE - "${COMPONENT_DIR}/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c" ) + if(CONFIG_MBEDTLS_SHA1_C) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha1.c" + ) + endif() + if(CONFIG_SOC_SHA_SUPPORT_SHA512 AND CONFIG_MBEDTLS_SHA512_C) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha512.c" + ) + endif() endif() if(CONFIG_SOC_ECC_SUPPORTED) @@ -120,6 +118,9 @@ if(CONFIG_SOC_HMAC_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_opaque.c") target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/esp_hmac_pbkdf2.c") target_link_libraries(tfpsacrypto PRIVATE idf::efuse) +else() + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c") endif() # PSA Attestation diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h b/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h index 9c915f4f20c..ed14b4d095b 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h @@ -40,7 +40,7 @@ #undef MBEDTLS_TIMING_C #define MBEDTLS_PLATFORM_C -#if CONFIG_MBEDTLS_HARDWARE_AES +#if SOC_AES_SUPPORTED #define ESP_AES_DRIVER_ENABLED #define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES #endif @@ -59,29 +59,41 @@ #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #else #undef PSA_WANT_ALG_DETERMINISTIC_ECDSA +#undef MBEDTLS_HMAC_DRBG_C #endif -#if CONFIG_MBEDTLS_SHA1_C -#define MBEDTLS_SHA1_C -#endif -#define MBEDTLS_SHA224_C -#define MBEDTLS_SHA256_C - #if SOC_SHA_SUPPORTED #define ESP_SHA_DRIVER_ENABLED -#define ESP_HMAC_TRANSPARENT_DRIVER_ENABLED -#undef MBEDTLS_PSA_BUILTIN_ALG_HMAC #if CONFIG_MBEDTLS_SHA1_C - #define MBEDTLS_PSA_ACCEL_ALG_SHA_1 - #undef MBEDTLS_PSA_BUILTIN_ALG_SHA_1 - #undef MBEDTLS_SHA1_C +#define MBEDTLS_PSA_ACCEL_ALG_SHA_1 +#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_1 +#undef MBEDTLS_SHA1_C +#else +#undef PSA_WANT_ALG_SHA_1 #endif +#define MBEDTLS_PSA_ACCEL_ALG_SHA_224 #undef MBEDTLS_PSA_BUILTIN_ALG_SHA_224 #undef MBEDTLS_SHA224_C -#define MBEDTLS_PSA_ACCEL_ALG_SHA_224 #undef MBEDTLS_PSA_BUILTIN_ALG_SHA_256 #define MBEDTLS_PSA_ACCEL_ALG_SHA_256 #undef MBEDTLS_SHA256_C +#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C +#define MBEDTLS_PSA_ACCEL_ALG_SHA_384 +#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_384 +#define MBEDTLS_PSA_ACCEL_ALG_SHA_512 +#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_512 +#undef MBEDTLS_SHA384_C +#undef MBEDTLS_SHA512_C +#else +#undef PSA_WANT_ALG_SHA_384 +#undef PSA_WANT_ALG_SHA_512 +#undef MBEDTLS_SHA512_ALT +#endif +#if !SOC_HMAC_SUPPORTED +#define ESP_HMAC_TRANSPARENT_DRIVER_ENABLED +#define MBEDTLS_PSA_ACCEL_ALG_HMAC +#undef MBEDTLS_PSA_BUILTIN_ALG_HMAC +#endif #endif #if SOC_ECC_SUPPORTED @@ -91,17 +103,6 @@ #if SOC_HMAC_SUPPORTED #define ESP_HMAC_OPAQUE_DRIVER_ENABLED -#else -#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_HMAC -#endif - -#if CONFIG_MBEDTLS_ROM_MD5 -#define ESP_MD5_DRIVER_ENABLED -#define MBEDTLS_PSA_ACCEL_ALG_MD5 -#undef MBEDTLS_PSA_BUILTIN_ALG_MD5 -#else -#undef PSA_WANT_ALG_MD5 -#undef MBEDTLS_MD5_C #endif #undef PSA_WANT_ECC_SECP_R1_192 @@ -122,21 +123,23 @@ #undef PSA_WANT_KEY_TYPE_DES #undef PSA_WANT_ALG_RIPEMD160 #undef PSA_WANT_ALG_CHACHA20 +#undef MBEDTLS_CHACHA20_C #undef PSA_WANT_ALG_CHACHA20_POLY1305 +#undef MBEDTLS_CHACHAPOLY_C #undef PSA_WANT_ALG_CCM #undef PSA_WANT_ALG_CMAC -#define MBEDTLS_AES_ROM_TABLES -#if SOC_AES_SUPPORTED -#define MBEDTLS_AES_FEWER_TABLES -#endif - /* Disable unused hash algorithms */ #undef PSA_WANT_ALG_MD5 +#undef MBEDTLS_MD5_C #undef PSA_WANT_ALG_SHA3_224 +#undef MBEDTLS_SHA3_224_C #undef PSA_WANT_ALG_SHA3_256 +#undef MBEDTLS_SHA3_256_C #undef PSA_WANT_ALG_SHA3_384 +#undef MBEDTLS_SHA3_384_C #undef PSA_WANT_ALG_SHA3_512 +#undef MBEDTLS_SHA3_512_C /* Disable RSA — not used by TEE */ #undef PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC @@ -164,11 +167,9 @@ #undef MBEDTLS_SSL_CLI_C #undef MBEDTLS_SSL_SRV_C -#undef PSA_WANT_ALG_PBKDF2_HMAC #undef PSA_WANT_ALG_TLS12_PRF +#undef PSA_WANT_ALG_PBKDF2_HMAC #undef PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 -#undef PSA_WANT_ALG_CCM -#undef PSA_WANT_ALG_CMAC #undef MBEDTLS_AES_C #define MBEDTLS_AES_ROM_TABLES diff --git a/components/mbedtls/port/aes/dma/esp_aes_dma_core.c b/components/mbedtls/port/aes/dma/esp_aes_dma_core.c index ac120a33630..544bb3a4e58 100644 --- a/components/mbedtls/port/aes/dma/esp_aes_dma_core.c +++ b/components/mbedtls/port/aes/dma/esp_aes_dma_core.c @@ -244,6 +244,7 @@ static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char unsigned char *output_buf = NULL; const unsigned char *dma_input; chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len); + const size_t alloc_chunk_len = chunk_len; size_t input_alignment = 1; size_t output_alignment = 1; @@ -313,10 +314,12 @@ static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char cleanup: - if (realloc_input) { + if (realloc_input && input_buf) { + mbedtls_platform_zeroize(input_buf, alloc_chunk_len); free(input_buf); } - if (realloc_output) { + if (realloc_output && output_buf) { + mbedtls_platform_zeroize(output_buf, alloc_chunk_len); free(output_buf); } @@ -459,7 +462,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le dma_descriptors = (crypto_dma_desc_t *) aes_dma_calloc(dma_descs_needed, sizeof(crypto_dma_desc_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, NULL); if (dma_descriptors == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for the array of DMA descriptors"); - return ESP_FAIL; + goto err; } size_t populated_dma_descs = 0; @@ -468,7 +471,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le start_alignment_stream_buffer = aes_dma_calloc(alignment_buffer_size, sizeof(uint8_t), AES_DMA_ALLOC_CAPS | (esp_ptr_external_ram(buffer) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL) , NULL); if (start_alignment_stream_buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for start alignment buffer"); - return ESP_FAIL; + goto err; } memset(start_alignment_stream_buffer, 0, unaligned_start_bytes); @@ -490,7 +493,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le end_alignment_stream_buffer = aes_dma_calloc(alignment_buffer_size, sizeof(uint8_t), AES_DMA_ALLOC_CAPS | (esp_ptr_external_ram(buffer) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL), NULL); if (end_alignment_stream_buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for end alignment buffer"); - return ESP_FAIL; + goto err; } memset(end_alignment_stream_buffer, 0, unaligned_end_bytes); @@ -504,7 +507,7 @@ static esp_err_t generate_descriptor_list(const uint8_t *buffer, const size_t le if (dma_desc_link(dma_descriptors, dma_descs_needed, cache_line_size) != ESP_OK) { ESP_LOGE(TAG, "DMA descriptors cache sync C2M failed"); - return ESP_FAIL; + goto err; } ret: @@ -525,6 +528,18 @@ ret: *end_alignment_buffer = end_alignment_stream_buffer; return ESP_OK; + +err: + if (start_alignment_stream_buffer) { + mbedtls_platform_zeroize(start_alignment_stream_buffer, alignment_buffer_size); + free(start_alignment_stream_buffer); + } + if (end_alignment_stream_buffer) { + mbedtls_platform_zeroize(end_alignment_stream_buffer, alignment_buffer_size); + free(end_alignment_stream_buffer); + } + free(dma_descriptors); + return ESP_FAIL; } int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out) @@ -589,19 +604,12 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign } size_t input_alignment_buffer_size = MAX(2 * input_cache_line_size, AES_BLOCK_BYTES); + size_t output_alignment_buffer_size = MAX(2 * output_cache_line_size, AES_BLOCK_BYTES); crypto_dma_desc_t *input_desc = NULL; uint8_t *input_start_stream_buffer = NULL; uint8_t *input_end_stream_buffer = NULL; - if (generate_descriptor_list(input, len, &input_start_stream_buffer, &input_end_stream_buffer, input_alignment_buffer_size, input_cache_line_size, NULL, NULL, &input_desc, NULL, false) != ESP_OK) { - mbedtls_platform_zeroize(output, len); - ESP_LOGE(TAG, "Generating input DMA descriptors failed"); - return -1; - } - - size_t output_alignment_buffer_size = MAX(2 * output_cache_line_size, AES_BLOCK_BYTES); - crypto_dma_desc_t *output_desc = NULL; uint8_t *output_start_stream_buffer = NULL; uint8_t *output_end_stream_buffer = NULL; @@ -609,10 +617,16 @@ int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsign size_t output_end_alignment = 0; size_t output_dma_desc_num = 0; + if (generate_descriptor_list(input, len, &input_start_stream_buffer, &input_end_stream_buffer, input_alignment_buffer_size, input_cache_line_size, NULL, NULL, &input_desc, NULL, false) != ESP_OK) { + ESP_LOGE(TAG, "Generating input DMA descriptors failed"); + ret = -1; + goto cleanup; + } + if (generate_descriptor_list(output, len, &output_start_stream_buffer, &output_end_stream_buffer, output_alignment_buffer_size, output_cache_line_size, &output_start_alignment, &output_end_alignment, &output_desc, &output_dma_desc_num, true) != ESP_OK) { - mbedtls_platform_zeroize(output, len); ESP_LOGE(TAG, "Generating output DMA descriptors failed"); - return -1; + ret = -1; + goto cleanup; } crypto_dma_desc_t *out_desc_tail = &output_desc[output_dma_desc_num - 1]; @@ -705,11 +719,23 @@ cleanup: mbedtls_platform_zeroize(output, len); } - free(input_start_stream_buffer); - free(input_end_stream_buffer); + if (input_start_stream_buffer) { + mbedtls_platform_zeroize(input_start_stream_buffer, input_alignment_buffer_size); + free(input_start_stream_buffer); + } + if (input_end_stream_buffer) { + mbedtls_platform_zeroize(input_end_stream_buffer, input_alignment_buffer_size); + free(input_end_stream_buffer); + } - free(output_start_stream_buffer); - free(output_end_stream_buffer); + if (output_start_stream_buffer) { + mbedtls_platform_zeroize(output_start_stream_buffer, output_alignment_buffer_size); + free(output_start_stream_buffer); + } + if (output_end_stream_buffer) { + mbedtls_platform_zeroize(output_end_stream_buffer, output_alignment_buffer_size); + free(output_end_stream_buffer); + } free(input_desc); free(output_desc); @@ -918,12 +944,24 @@ cleanup: free(aad_end_stream_buffer); free(aad_desc); - free(input_start_stream_buffer); - free(input_end_stream_buffer); + if (input_start_stream_buffer) { + mbedtls_platform_zeroize(input_start_stream_buffer, input_alignment_buffer_size); + free(input_start_stream_buffer); + } + if (input_end_stream_buffer) { + mbedtls_platform_zeroize(input_end_stream_buffer, input_alignment_buffer_size); + free(input_end_stream_buffer); + } free(input_desc); - free(output_start_stream_buffer); - free(output_end_stream_buffer); + if (output_start_stream_buffer) { + mbedtls_platform_zeroize(output_start_stream_buffer, output_alignment_buffer_size); + free(output_start_stream_buffer); + } + if (output_end_stream_buffer) { + mbedtls_platform_zeroize(output_end_stream_buffer, output_alignment_buffer_size); + free(output_end_stream_buffer); + } free(output_desc); free(len_buf); diff --git a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c index 59e3b9cb665..028c5a72e60 100644 --- a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c +++ b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c @@ -50,6 +50,7 @@ static psa_status_t esp_crypto_aes_gcm_setup( status = mbedtls_to_psa_error(esp_aes_gcm_setkey(ctx, 2, key_buffer, key_buffer_size * 8)); if (status != PSA_SUCCESS) { + esp_aes_gcm_free(ctx); free(ctx); goto exit; } diff --git a/components/mbedtls/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c b/components/mbedtls/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c index 118d8ef55cf..01bb37963d5 100644 --- a/components/mbedtls/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c +++ b/components/mbedtls/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c @@ -17,12 +17,12 @@ psa_status_t esp_hmac_abort_transparent(esp_hmac_transparent_operation_t *esp_hm { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg); if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_abort(&esp_hmac_ctx->md5_ctx); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx); } @@ -69,9 +69,9 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm memset(esp_hmac_ctx->opad, 0, PSA_HMAC_MAX_HASH_BLOCK_SIZE); if ( -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) hash_alg != PSA_ALG_MD5 && -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) (hash_alg < PSA_ALG_SHA_1 #if SOC_SHA_SUPPORT_SHA512 || hash_alg > PSA_ALG_SHA_512 @@ -96,12 +96,12 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm } if (key_buffer_size > block_size) { -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_compute(hash_alg, key_buffer, key_buffer_size, ipad, sizeof(ipad), &key_buffer_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_compute(hash_alg, key_buffer, key_buffer_size, ipad, sizeof(ipad), &key_buffer_size); @@ -164,11 +164,11 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm memset(esp_hmac_ctx->opad + key_buffer_size, 0x5C, fill_size); } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_setup(&esp_hmac_ctx->md5_ctx, hash_alg); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg); } @@ -176,11 +176,11 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm goto error; } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_update(&esp_hmac_ctx->md5_ctx, ipad, block_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, ipad, block_size); } @@ -202,12 +202,12 @@ psa_status_t esp_hmac_update_transparent(esp_hmac_transparent_operation_t *esp_h return PSA_ERROR_INVALID_ARGUMENT; } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg); if (hash_alg == PSA_ALG_MD5) { return esp_md5_hash_update(&esp_hmac_ctx->md5_ctx, data, data_length); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { return esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, data, data_length); } @@ -231,11 +231,11 @@ psa_status_t esp_hmac_finish_transparent( size_t hash_size = 0; size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_finish(&esp_hmac_ctx->md5_ctx, tmp, sizeof(tmp), &hash_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size); } @@ -244,11 +244,11 @@ psa_status_t esp_hmac_finish_transparent( } /* From here on, tmp needs to be wiped. */ -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_setup(&esp_hmac_ctx->md5_ctx, hash_alg); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg); } @@ -256,11 +256,11 @@ psa_status_t esp_hmac_finish_transparent( goto exit; } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_update(&esp_hmac_ctx->md5_ctx, esp_hmac_ctx->opad, block_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, esp_hmac_ctx->opad, block_size); } @@ -268,11 +268,11 @@ psa_status_t esp_hmac_finish_transparent( goto exit; } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_update(&esp_hmac_ctx->md5_ctx, tmp, hash_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, tmp, hash_size); } @@ -280,11 +280,11 @@ psa_status_t esp_hmac_finish_transparent( goto exit; } -#if CONFIG_MBEDTLS_ROM_MD5 +#if defined(ESP_MD5_DRIVER_ENABLED) if (hash_alg == PSA_ALG_MD5) { status = esp_md5_hash_finish(&esp_hmac_ctx->md5_ctx, tmp, sizeof(tmp), &hash_size); } else -#endif // CONFIG_MBEDTLS_ROM_MD5 +#endif // defined(ESP_MD5_DRIVER_ENABLED) { status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size); } diff --git a/components/mbedtls/port/psa_driver/esp_rsa_ds/psa_crypto_driver_esp_rsa_ds.c b/components/mbedtls/port/psa_driver/esp_rsa_ds/psa_crypto_driver_esp_rsa_ds.c index 44d8c8c97dc..b91da62ac48 100644 --- a/components/mbedtls/port/psa_driver/esp_rsa_ds/psa_crypto_driver_esp_rsa_ds.c +++ b/components/mbedtls/port/psa_driver/esp_rsa_ds/psa_crypto_driver_esp_rsa_ds.c @@ -19,6 +19,8 @@ #include "esp_assert.h" #include "soc/soc_caps.h" +#include "mbedtls/platform_util.h" + #if SOC_KEY_MANAGER_SUPPORTED #include "esp_key_mgr.h" #endif /* SOC_KEY_MANAGER_SUPPORTED */ @@ -500,6 +502,7 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_start( error: if (em) { + mbedtls_platform_zeroize(em, rsa_len_bytes); heap_caps_free(em); em = NULL; } @@ -830,6 +833,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt( err = esp_key_mgr_activate_key(km_ri); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to activate key: 0x%x", err); + mbedtls_platform_zeroize(em_words, sizeof(uint32_t) * data_len); heap_caps_free(em_words); esp_rsa_ds_release_ds_lock(); return PSA_ERROR_INVALID_HANDLE; @@ -844,6 +848,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt( hmac_key_id, &ds_ctx); if (err != ESP_OK) { + mbedtls_platform_zeroize(em_words, sizeof(uint32_t) * data_len); heap_caps_free(em_words); #if SOC_KEY_MANAGER_SUPPORTED if (is_km_key_active) { @@ -863,6 +868,7 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt( #endif /* SOC_KEY_MANAGER_SUPPORTED */ if (err != ESP_OK) { + mbedtls_platform_zeroize(em_words, sizeof(uint32_t) * data_len); heap_caps_free(em_words); esp_rsa_ds_release_ds_lock(); return PSA_ERROR_GENERIC_ERROR; diff --git a/components/mbedtls/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c b/components/mbedtls/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c index e3d4cf5aba0..8c3feda61d4 100644 --- a/components/mbedtls/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c +++ b/components/mbedtls/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c @@ -12,6 +12,7 @@ #include "include/psa_crypto_driver_esp_sha512.h" #include "psa/crypto.h" #include "psa/crypto_sizes.h" +#include "mbedtls/platform_util.h" #include "esp_log.h" #include "esp_heap_caps.h" @@ -229,6 +230,7 @@ psa_status_t esp_sha_hash_finish( if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) { esp_sha1_context *ctx = (esp_sha1_context *)operation->sha_ctx; int ret = esp_sha1_driver_finish(ctx, hash, hash_size, hash_length); + mbedtls_platform_zeroize(ctx, sizeof(esp_sha1_context)); free(ctx); // Free the context after use operation->sha_ctx = NULL; return ret; @@ -239,6 +241,7 @@ psa_status_t esp_sha_hash_finish( operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) { esp_sha256_context *ctx = (esp_sha256_context *)operation->sha_ctx; int ret = esp_sha256_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type); + mbedtls_platform_zeroize(ctx, sizeof(esp_sha256_context)); free(ctx); // Free the context after use operation->sha_ctx = NULL; return ret; @@ -249,6 +252,7 @@ psa_status_t esp_sha_hash_finish( operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) { esp_sha512_context *ctx = (esp_sha512_context *)operation->sha_ctx; int ret = esp_sha512_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type); + mbedtls_platform_zeroize(ctx, sizeof(esp_sha512_context)); free(ctx); // Free the context after use operation->sha_ctx = NULL; return ret; diff --git a/components/mbedtls/port/sha/core/sha.c b/components/mbedtls/port/sha/core/sha.c index 2e63b155df7..8544ddddb80 100644 --- a/components/mbedtls/port/sha/core/sha.c +++ b/components/mbedtls/port/sha/core/sha.c @@ -27,6 +27,7 @@ #include "esp_crypto_dma.h" #include "esp_heap_caps.h" #include "hal/dma_types.h" +#include "mbedtls/platform_util.h" #include "soc/ext_mem_defs.h" #include "soc/periph_defs.h" @@ -186,6 +187,10 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu buf_copy = heap_caps_aligned_alloc(SOC_GDMA_EXT_MEM_ENC_ALIGNMENT, buf_len, heap_caps); if (buf_copy == NULL) { ESP_LOGE(TAG, "Failed to allocate aligned internal memory"); + if (input_copy) { + mbedtls_platform_zeroize(input_copy, ilen); + free(input_copy); + } return ret; } memcpy(buf_copy, buf, buf_len); @@ -197,10 +202,12 @@ static esp_err_t esp_sha_dma_process_ext(esp_sha_type sha_type, const void *inpu ret = esp_sha_dma_process(sha_type, dma_input, ilen, dma_buf, buf_len, is_first_block); if (realloc_input) { + mbedtls_platform_zeroize(input_copy, ilen); free(input_copy); } if (realloc_buf) { + mbedtls_platform_zeroize(buf_copy, buf_len); free(buf_copy); } @@ -318,6 +325,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, { int ret = 0; unsigned char *dma_cap_buf = NULL; + uint32_t dma_cap_buf_len = 0; if (buf_len > block_length(sha_type)) { ESP_LOGE(TAG, "SHA DMA buf_len cannot exceed max size for a single block"); @@ -339,6 +347,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, goto cleanup; } memcpy(dma_cap_buf, buf, buf_len); + dma_cap_buf_len = buf_len; buf = dma_cap_buf; } @@ -375,7 +384,10 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, } cleanup: - free(dma_cap_buf); + if (dma_cap_buf) { + mbedtls_platform_zeroize(dma_cap_buf, dma_cap_buf_len); + free(dma_cap_buf); + } return ret; } #endif /* SOC_SHA_SUPPORT_DMA */ diff --git a/docs/en/security/tee/tee-attestation.rst b/docs/en/security/tee/tee-attestation.rst index 672067e74cb..2d45bcf9a18 100644 --- a/docs/en/security/tee/tee-attestation.rst +++ b/docs/en/security/tee/tee-attestation.rst @@ -107,6 +107,12 @@ EAT: Claim Table * - Client ID - Relying Party identification - + * - Chip ID + - SoC chip identifier + - + * - UEID + - Universal Entity Identifiers, factory-burnt in eFuse + - Device MAC address and the Optional Unique ID from eFuse * - Device ID - Device identification (should be unique) - SHA256 digest of the device MAC address @@ -176,9 +182,14 @@ Sample EAT in JSON format "key_id": "tee_att_key0" }, "eat": { - "auth_challenge":"dcb9b53143ad6b081dad1a05c7ebda4e314d388762215799cf24ed52e9387678" + "auth_challenge":"dcb9b53143ad6b081dad1a05c7ebda4e314d388762215799cf24ed52e9387678", "client_id": 262974944, + "chip_id": 13, "device_ver": 1, + "ueid": { + "mac": "d885ac67c978", + "optional_id": "94fa4d7e305682714d48e7bbd710c961" + }, "device_id": "e8cddb2a7f9a5a7c61735d6dda26e4bd153c6d772a9be6f26bd321dfe25e0ac8", "instance_id": "1adba85e0df997fd961f25a9e312430cef162b5c69466cd5b172f1e65ac7360c", "psa_cert_ref": "0716053550477-10100", diff --git a/examples/security/.build-test-rules.yml b/examples/security/.build-test-rules.yml index 3657f732b6e..fd3da7181ec 100644 --- a/examples/security/.build-test-rules.yml +++ b/examples/security/.build-test-rules.yml @@ -60,7 +60,6 @@ examples/security/tee/tee_attestation: disable: - if: IDF_TARGET not in ["esp32c6", "esp32c61"] depends_components: - - *common_components - esp_tee depends_filepatterns: - examples/security/tee/tee_attestation/**/* @@ -69,7 +68,6 @@ examples/security/tee/tee_basic: disable: - if: IDF_TARGET not in ["esp32c6", "esp32c61"] depends_components: - - *common_components - esp_tee depends_filepatterns: - examples/security/tee/tee_basic/**/* @@ -78,7 +76,6 @@ examples/security/tee/tee_secure_ota: disable: - if: IDF_TARGET not in ["esp32c6", "esp32c61"] depends_components: - - *common_components - esp_tee - protocol_examples_common depends_filepatterns: @@ -88,7 +85,6 @@ examples/security/tee/tee_secure_storage: disable: - if: IDF_TARGET not in ["esp32c6", "esp32c61"] depends_components: - - *common_components - esp_tee depends_filepatterns: - examples/security/tee/tee_secure_storage/**/* diff --git a/examples/security/tee/tee_attestation/README.md b/examples/security/tee/tee_attestation/README.md index 72b87ce690a..5b2dd6bfd48 100644 --- a/examples/security/tee/tee_attestation/README.md +++ b/examples/security/tee/tee_attestation/README.md @@ -28,7 +28,12 @@ "eat": { "auth_challenge": "dcb9b53143ad6b081dad1a05c7ebda4e314d388762215799cf24ed52e9387678", "client_id": 262974944, + "chip_id": 13, "device_ver": 1, + "ueid": { + "mac": "d885ac67c978", + "optional_id": "94fa4d7e305682714d48e7bbd710c961" + }, "device_id": "e8cddb2a7f9a5a7c61735d6dda26e4bd153c6d772a9be6f26bd321dfe25e0ac8", "instance_id": "1adba85e0df997fd961f25a9e312430cef162b5c69466cd5b172f1e65ac7360c", "psa_cert_ref": "0716053550477-10100", @@ -127,9 +132,9 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ```log I (438) example_tee_attest: TEE Attestation Service -I (1008) example_tee_attest: Attestation token - Length: 1538 +I (1008) example_tee_attest: Attestation token - Length: 1705 I (1018) example_tee_attest: Attestation token - Data: -'{"header":{"magic":"44fef7cc","encr_alg":"","sign_alg":"ecdsa_secp256r1_sha256","key_id":"tee_att_key0"},"eat":{"nonce":-1582119980,"client_id":262974944,"device_ver":1,"device_id":"4ecc458ef4290329552b4dcdccb99d55e5ea7624f24c87b27b71515e1666f39c","instance_id":"66571b78918f4bb7ae2723f235a9e4fe1c7070ae6261ce5df7049b44b1f8a318","psa_cert_ref":"0716053550477-10100","device_status":165,"sw_claims":{"tee":{"type":1,"ver":"1.0.0","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"5213904fd8ca7538776bdf372c08c13138f20b2fac3503bc878f19c6e36a710d","digest_validated":true,"sign_verified":false,"secure_padding":false}},"app":{"type":2,"ver":"v0.1.0","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"65c905fc0fc135fdfa8def210d1c186627cb3a17ecb2e7f020b56411b2d2fc76","digest_validated":true,"sign_verified":false,"secure_padding":false}},"bootloader":{"type":0,"ver":"01000000","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"9efd37d29266f3239f7c6a095df880f1e85e41505f154cfd3bbfad4b8a2b18dd","digest_validated":true,"sign_verified":false}}}},"public_key":{"compressed":"02ce0188c61b0118c86ca20af7e01185dd687c6698b2265a288fee845d083e9066"},"sign":{"r":"362e2053bab26c779559793b2eae89e96c1a058e5fffc49d544d07b934ce3b32","s":"fc5f0e4d329fc6e031cbf425ef62d4756b728392b2a77282baa1f15b554d2716"}}' +'{"header":{"magic":"44fef7cc","encr_alg":"","sign_alg":"ecdsa_secp256r1_sha256","key_id":"tee_att_key0"},"eat":{"nonce":-1582119980,"client_id":262974944,"chip_id":13,"device_ver":1,"ueid":{"mac":"d885ac67c978","optional_id":"94fa4d7e305682714d48e7bbd710c961"},"device_id":"4ecc458ef4290329552b4dcdccb99d55e5ea7624f24c87b27b71515e1666f39c","instance_id":"66571b78918f4bb7ae2723f235a9e4fe1c7070ae6261ce5df7049b44b1f8a318","psa_cert_ref":"0716053550477-10100","device_status":165,"sw_claims":{"tee":{"type":1,"ver":"1.0.0","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"5213904fd8ca7538776bdf372c08c13138f20b2fac3503bc878f19c6e36a710d","digest_validated":true,"sign_verified":false,"secure_padding":false}},"app":{"type":2,"ver":"v0.1.0","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"65c905fc0fc135fdfa8def210d1c186627cb3a17ecb2e7f020b56411b2d2fc76","digest_validated":true,"sign_verified":false,"secure_padding":false}},"bootloader":{"type":0,"ver":"01000000","idf_ver":"v5.5-dev-2978-gd75a0105dac-dirt","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"9efd37d29266f3239f7c6a095df880f1e85e41505f154cfd3bbfad4b8a2b18dd","digest_validated":true,"sign_verified":false}}}},"public_key":{"compressed":"02ce0188c61b0118c86ca20af7e01185dd687c6698b2265a288fee845d083e9066"},"sign":{"r":"362e2053bab26c779559793b2eae89e96c1a058e5fffc49d544d07b934ce3b32","s":"fc5f0e4d329fc6e031cbf425ef62d4756b728392b2a77282baa1f15b554d2716"}}' I (1148) main_task: Returned from app_main() ``` diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index f2f51aa9463..4ba573982dc 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -155,6 +155,8 @@ components_not_formatted_permanent: - /components/esp_system/openocd_stub_bins/*.inc - /components/esp_system/openocd_stub_bins/esp32c6/*.inc - /components/esp_system/openocd_stub_bins/esp32h2/*.inc + # TEE ASM helper macros — .inc file, not C include files + - /components/esp_tee/subproject/main/arch/riscv/*.inc docs: # Docs directory contains some .inc files, which are not C include files