diff --git a/components/bootloader_support/private_include/bootloader_sha.h b/components/bootloader_support/private_include/bootloader_sha.h index b4eec76484c..661aa8028ee 100644 --- a/components/bootloader_support/private_include/bootloader_sha.h +++ b/components/bootloader_support/private_include/bootloader_sha.h @@ -9,7 +9,7 @@ that can be used from bootloader or app code. This header is available to source code in the bootloader & bootloader_support components only. - Use mbedTLS APIs or include esp32/sha.h to calculate SHA256 in IDF apps. + Use PSA APIs or include esp32/sha.h to calculate SHA256 in IDF apps. */ #include diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index e4b553a5b7d..d771e1caf85 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -179,81 +179,117 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest #else /* NON_OS_BUILD || CONFIG_APP_BUILD_TYPE_RAM */ #include "bootloader_flash_priv.h" -#include -#include +#include "psa/crypto.h" bootloader_sha256_handle_t bootloader_sha256_start(void) { - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context)); - if (!ctx) { + psa_hash_operation_t *op = (psa_hash_operation_t *)malloc(sizeof(psa_hash_operation_t)); + if (!op) { return NULL; } - mbedtls_sha256_init(ctx); - int ret = mbedtls_sha256_starts(ctx, false); - if (ret != 0) { + + *op = psa_hash_operation_init(); + psa_status_t status = psa_hash_setup(op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + free(op); return NULL; } - return ctx; + + return (bootloader_sha256_handle_t)op; } void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) { assert(handle != NULL); - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - int ret = mbedtls_sha256_update(ctx, data, data_len); - assert(ret == 0); - (void)ret; + psa_hash_operation_t *op = (psa_hash_operation_t *)handle; + + psa_status_t status = psa_hash_update(op, data, data_len); + assert(status == PSA_SUCCESS); + (void)status; // Suppress unused variable warning in release builds } void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) { assert(handle != NULL); - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; + psa_hash_operation_t *op = (psa_hash_operation_t *)handle; + if (digest != NULL) { - int ret = mbedtls_sha256_finish(ctx, digest); - assert(ret == 0); - (void)ret; + size_t hash_len; + psa_status_t status = psa_hash_finish(op, digest, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &hash_len); + assert(status == PSA_SUCCESS); + assert(hash_len == PSA_HASH_LENGTH(PSA_ALG_SHA_256)); + (void)status; // Suppress unused variable warning in release builds + (void)hash_len; // Suppress unused variable warning in release builds + } else { + psa_hash_abort(op); } - mbedtls_sha256_free(ctx); + free(handle); handle = NULL; } #if SOC_SHA_SUPPORT_SHA512 + +typedef struct { + psa_hash_operation_t *hash_op; + int psa_alg; +} bootloader_psa_sha_handle_t; + bootloader_sha_handle_t bootloader_sha512_start(bool is384) { - mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context)); - if (!ctx) { + psa_status_t status; + bootloader_psa_sha_handle_t *op = (bootloader_psa_sha_handle_t *)malloc(sizeof(bootloader_psa_sha_handle_t)); + if (!op) { return NULL; } - mbedtls_sha512_init(ctx); - int ret = mbedtls_sha512_starts(ctx, is384); - if (ret != 0) { + + op->hash_op = (psa_hash_operation_t *)malloc(sizeof(psa_hash_operation_t)); + if (!op->hash_op) { + free(op); return NULL; } - return ctx; + + op->psa_alg = is384 ? PSA_ALG_SHA_384 : PSA_ALG_SHA_512; + + *op->hash_op = psa_hash_operation_init(); + status = psa_hash_setup(op->hash_op, op->psa_alg); + if (status != PSA_SUCCESS) { + free(op->hash_op); + free(op); + return NULL; + } + + return (bootloader_psa_sha_handle_t *)op; } void bootloader_sha512_data(bootloader_sha_handle_t handle, const void *data, size_t data_len) { assert(handle != NULL); - mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle; - int ret = mbedtls_sha512_update(ctx, data, data_len); - assert(ret == 0); - (void)ret; + bootloader_psa_sha_handle_t *op = (bootloader_psa_sha_handle_t *)handle; + + psa_status_t status = psa_hash_update(op->hash_op, data, data_len); + assert(status == PSA_SUCCESS); + (void)status; // Suppress unused variable warning in release builds } void bootloader_sha512_finish(bootloader_sha_handle_t handle, uint8_t *digest) { assert(handle != NULL); - mbedtls_sha512_context *ctx = (mbedtls_sha512_context *)handle; + bootloader_psa_sha_handle_t *op = (bootloader_psa_sha_handle_t *)handle; + if (digest != NULL) { - int ret = mbedtls_sha512_finish(ctx, digest); - assert(ret == 0); - (void)ret; + size_t hash_len; + psa_status_t status = psa_hash_finish(op->hash_op, digest, PSA_HASH_LENGTH(op->psa_alg), &hash_len); + assert(status == PSA_SUCCESS); + assert(hash_len == PSA_HASH_LENGTH(op->psa_alg)); + (void)status; // Suppress unused variable warning in release builds + (void)hash_len; // Suppress unused variable warning in release builds + } else { + psa_hash_abort(op->hash_op); } - mbedtls_sha512_free(ctx); - free(handle); + + free(op->hash_op); + free(op); handle = NULL; } #endif /* SOC_SHA_SUPPORT_SHA512 */ diff --git a/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c index c7057014cf3..92be1b5a52a 100644 --- a/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c +++ b/components/bootloader_support/src/secure_boot_v1/secure_boot_signatures_app.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,14 +11,11 @@ #include "esp_log.h" #include "esp_image_format.h" #include "esp_secure_boot.h" -#include "mbedtls/sha256.h" -#include "mbedtls/x509.h" -#include "mbedtls/md.h" -#include "mbedtls/platform.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" +#include "psa/crypto.h" #include #include +#include "mbedtls/pk.h" + #ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME ESP_LOG_ATTR_TAG(TAG, "secure_boot_v1"); @@ -27,7 +24,9 @@ extern const uint8_t signature_verification_key_start[] asm("_binary_signature_v extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end"); #define SIGNATURE_VERIFICATION_KEYLEN 64 - +#define PSA_ECDSA_PUB_KEY_SIZE_BITS 256 +#define UNCOMPRESSED_SECP256R1_KEY_SIZE 65 // Size for uncompressed SECP256R1 (1 + 32 + 32) +#define ECC_UNCOMPRESSED_POINT_FORMAT_INDICATOR 0x04 esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) { uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN]; @@ -76,53 +75,47 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig } ESP_LOGD(TAG, "Verifying secure boot signature"); + psa_status_t status; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_handle; - int ret; - mbedtls_mpi r, s; + // Format the public key for PSA import + uint8_t formatted_key[UNCOMPRESSED_SECP256R1_KEY_SIZE]; + formatted_key[0] = ECC_UNCOMPRESSED_POINT_FORMAT_INDICATOR; - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - /* Extract r and s components from RAW ECDSA signature of 64 bytes */ -#define ECDSA_INTEGER_LEN 32 - ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret); + // Copy X and Y coordinates + if (keylen == 64) { // Raw coordinates without format byte + memcpy(&formatted_key[1], signature_verification_key_start, 64); + } else if (keylen == UNCOMPRESSED_SECP256R1_KEY_SIZE && signature_verification_key_start[0] == ECC_UNCOMPRESSED_POINT_FORMAT_INDICATOR) { + // Key is already in correct format + memcpy(formatted_key, signature_verification_key_start, UNCOMPRESSED_SECP256R1_KEY_SIZE); + } else { + ESP_LOGE(TAG, "Invalid key format or length"); return ESP_FAIL; } - ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret); - mbedtls_mpi_free(&r); + // Set key attributes + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&key_attributes, PSA_ECDSA_PUB_KEY_SIZE_BITS); + + // Import the properly formatted public key + status = psa_import_key(&key_attributes, formatted_key, sizeof(formatted_key), &key_handle); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Failed to import key, status:%d", status); return ESP_FAIL; } - /* Initialise ECDSA context */ - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); + // Verify the signature + status = psa_verify_hash(key_handle, PSA_ALG_ECDSA(PSA_ALG_SHA_256), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, sig_block->signature, SIGNATURE_VERIFICATION_KEYLEN); + ESP_LOGI(TAG, "Verification result %d", status); - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); - size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); - if (keylen != 2 * plen) { - ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen); - ret = ESP_FAIL; - goto cleanup; - } + // Destroy the key handle + psa_destroy_key(key_handle); + psa_reset_key_attributes(&key_attributes); - /* Extract X and Y components from ECDSA public key */ - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), signature_verification_key_start, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), signature_verification_key_start + plen, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1)); - - ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s); - ESP_LOGD(TAG, "Verification result %d", ret); - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - mbedtls_ecdsa_free(&ecdsa_context); - return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID; + return status == PSA_SUCCESS ? ESP_OK : ESP_ERR_IMAGE_INVALID; #endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED } #endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot_ecdsa_signature.c b/components/bootloader_support/src/secure_boot_v2/secure_boot_ecdsa_signature.c index 2eeff0da558..6f716b24e16 100644 --- a/components/bootloader_support/src/secure_boot_v2/secure_boot_ecdsa_signature.c +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot_ecdsa_signature.c @@ -5,15 +5,9 @@ */ #include "esp_log.h" #include "esp_secure_boot.h" -#include "mbedtls/sha256.h" -#include "mbedtls/x509.h" -#include "mbedtls/md.h" -#include "mbedtls/platform.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/ecp.h" #include "rom/ecdsa.h" #include "sdkconfig.h" +#include "psa/crypto.h" #include "secure_boot_signature_priv.h" @@ -31,32 +25,35 @@ esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_bl return ESP_ERR_INVALID_ARG; } - esp_err_t ret; + esp_err_t ret = ESP_OK; + psa_status_t status; - mbedtls_mpi r, s; + /* Prepare public key for verification */ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_handle = 0; - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - /* Initialise ECDSA context */ - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); + /* Set key attributes according to the curve */ + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH); uint8_t key_size = 0; + psa_ecc_family_t curve_family; switch(trusted_block->ecdsa.key.curve_id) { case ECDSA_CURVE_P192: key_size = 24; - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1); + curve_family = PSA_ECC_FAMILY_SECP_R1; + psa_set_key_bits(&key_attributes, PSA_BYTES_TO_BITS(key_size)); break; case ECDSA_CURVE_P256: key_size = 32; - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); + curve_family = PSA_ECC_FAMILY_SECP_R1; + psa_set_key_bits(&key_attributes, PSA_BYTES_TO_BITS(key_size)); break; #if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS case ECDSA_CURVE_P384: key_size = 48; - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP384R1); + curve_family = PSA_ECC_FAMILY_SECP_R1; + psa_set_key_bits(&key_attributes, PSA_BYTES_TO_BITS(key_size)); break; #endif /* CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS */ default: @@ -64,50 +61,58 @@ esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_bl return ESP_ERR_INVALID_ARG; } - uint8_t x_point[ECDSA_INTEGER_LEN] = {}; - uint8_t y_point[ECDSA_INTEGER_LEN] = {}; - uint8_t _r[ECDSA_INTEGER_LEN] = {}; - uint8_t _s[ECDSA_INTEGER_LEN] = {}; + psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve_family)); - /* Convert r and s components to big endian format */ + /* Prepare the public key data from X and Y coordinates */ + uint8_t public_key[(2 * ECDSA_INTEGER_LEN) + 1]; + uint8_t x_point[ECDSA_INTEGER_LEN] = {0}; + uint8_t y_point[ECDSA_INTEGER_LEN] = {0}; + + /* Convert key points from little-endian to big-endian format */ for (int i = 0; i < key_size; i++) { - _r[i] = trusted_block->ecdsa.signature[key_size - i - 1]; - _s[i] = trusted_block->ecdsa.signature[2 * key_size - i - 1]; + x_point[i] = trusted_block->ecdsa.key.point[key_size - i - 1]; + + y_point[i] = trusted_block->ecdsa.key.point[2 * key_size - i - 1]; } - /* Extract r and s components from RAW ECDSA signature of 64 bytes */ - ret = mbedtls_mpi_read_binary(&r, _r, key_size); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(r), err:%d", ret); - mbedtls_ecdsa_free(&ecdsa_context); - return ESP_FAIL; + public_key[0] = 0x04; /* Uncompressed point format */ + + /* Combine X and Y into a single public key buffer */ + memcpy(public_key + 1, x_point, key_size); + memcpy(public_key + 1 + key_size, y_point, key_size); + + /* Import the public key */ + status = psa_import_key(&key_attributes, public_key, (2 * key_size) + 1, &key_handle); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Failed to import key, err:%d", status); + ret = ESP_FAIL; + goto cleanup; } - ret = mbedtls_mpi_read_binary(&s, _s, key_size); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(s), err:%d", ret); - mbedtls_mpi_free(&r); - mbedtls_ecdsa_free(&ecdsa_context); - return ESP_FAIL; + /* Convert signature from little-endian to big-endian format */ + uint8_t signature[2 * ECDSA_INTEGER_LEN] = {0}; + for (int i = 0; i < key_size; i++) { + signature[i] = trusted_block->ecdsa.signature[key_size - i - 1]; + signature[key_size + i] = trusted_block->ecdsa.signature[2 * key_size - i - 1]; } - size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); + /* Verify the signature */ + status = psa_verify_hash(key_handle, PSA_ALG_ECDSA(PSA_ALG_SHA_256), + image_digest, ESP_SECURE_BOOT_DIGEST_LEN, + signature, 2 * key_size); - for (int i = 0; i < plen; i++) { - x_point[i] = trusted_block->ecdsa.key.point[plen - 1 - i]; - y_point[i] = trusted_block->ecdsa.key.point[2 * plen - 1 - i]; + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Signature verification failed, err:%d", status); + ret = ESP_FAIL; } - /* Extract X and Y components from ECDSA public key */ - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), x_point, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), y_point, plen)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1)); - - ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s); - cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - mbedtls_ecdsa_free(&ecdsa_context); + /* Clean up resources */ + if (key_handle) { + psa_destroy_key(key_handle); + } + psa_reset_key_attributes(&key_attributes); + return ret; } diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot_rsa_signature.c b/components/bootloader_support/src/secure_boot_v2/secure_boot_rsa_signature.c index ce63ba9bcc7..7f815214f67 100644 --- a/components/bootloader_support/src/secure_boot_v2/secure_boot_rsa_signature.c +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot_rsa_signature.c @@ -1,76 +1,166 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "esp_log.h" #include "esp_secure_boot.h" -#include "mbedtls/sha256.h" +#include "psa/crypto.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" #include "mbedtls/x509.h" -#include "mbedtls/md.h" -#include "mbedtls/platform.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" #include "secure_boot_signature_priv.h" ESP_LOG_ATTR_TAG(TAG, "secure_boot_v2_rsa"); +/* + * Helper function to encode RSA public key (N, e) into DER format manually + * This creates a PKCS#1 RSAPublicKey structure: + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int encode_rsa_pubkey_der(const uint8_t *modulus, size_t modulus_len, + const uint8_t *exponent, size_t exponent_len, + uint8_t *der_buf, size_t der_buf_size, + uint8_t **der_start, size_t *der_len) +{ + if (!der_buf || !der_start || !der_len || der_buf_size == 0) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + int ret; + unsigned char *c = der_buf + der_buf_size; + size_t len = 0; + + /* Write the exponent (e) as an INTEGER */ + /* Skip leading zeros in exponent */ + while (exponent_len > 0 && *exponent == 0) { + exponent++; + exponent_len--; + } + + /* Write exponent */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, der_buf, exponent, exponent_len)); + + /* Add padding byte if MSB is set (to keep it positive) */ + if (exponent_len > 0 && (exponent[0] & 0x80)) { + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, der_buf, (const unsigned char *)"\x00", 1)); + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, der_buf, exponent_len + ((exponent[0] & 0x80) ? 1 : 0))); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, der_buf, MBEDTLS_ASN1_INTEGER)); + + /* Write the modulus (N) as an INTEGER */ + /* Skip leading zeros in modulus */ + const uint8_t *mod_ptr = modulus; + size_t mod_len = modulus_len; + while (mod_len > 0 && *mod_ptr == 0) { + mod_ptr++; + mod_len--; + } + + /* Write modulus */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, der_buf, mod_ptr, mod_len)); + + /* Add padding byte if MSB is set */ + if (mod_len > 0 && (mod_ptr[0] & 0x80)) { + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, der_buf, (const unsigned char *)"\x00", 1)); + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, der_buf, mod_len + ((mod_ptr[0] & 0x80) ? 1 : 0))); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, der_buf, MBEDTLS_ASN1_INTEGER)); + + /* Write SEQUENCE header */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, der_buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, der_buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + *der_start = c; + *der_len = len; + + return 0; +} + esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block) { if (!sig_block || !image_digest || !trusted_block) { return ESP_ERR_INVALID_ARG; } - int ret = 0; - mbedtls_rsa_context pk; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; + esp_err_t ret = ESP_OK; + psa_status_t status; const unsigned rsa_key_size = sizeof(sig_block->block[0].signature); - unsigned char *sig_be = calloc(1, rsa_key_size); + unsigned char *sig_be = NULL; + unsigned char *pubkey_der_buf = NULL; + + sig_be = calloc(1, rsa_key_size); if (sig_be == NULL) { return ESP_ERR_NO_MEM; } - unsigned char *buf = calloc(1, rsa_key_size); - if (buf == NULL) { + + /* Create key attributes for RSA public key */ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + + /* Allocate buffer for DER-encoded public key */ + size_t pubkey_der_buf_size = PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(3072); + pubkey_der_buf = calloc(1, pubkey_der_buf_size); + if (pubkey_der_buf == NULL) { free(sig_be); return ESP_ERR_NO_MEM; } - mbedtls_entropy_init(&entropy); - mbedtls_ctr_drbg_init(&ctr_drbg); - ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); - if (ret != 0) { - ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x", ret); - goto exit_outer; + /* Convert raw N and e to DER format manually */ + uint8_t *der_start = NULL; + size_t der_len = 0; + + /* Convert modulus from little-endian to big-endian */ + uint8_t *n_be = calloc(1, rsa_key_size); + if (n_be == NULL) { + free(sig_be); + free(pubkey_der_buf); + return ESP_ERR_NO_MEM; + } + for (size_t i = 0; i < rsa_key_size; i++) { + n_be[i] = trusted_block->key.n[rsa_key_size - 1 - i]; } - const mbedtls_mpi N = { .MBEDTLS_PRIVATE(s) = 1, - .MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.n)/sizeof(mbedtls_mpi_uint), - .MBEDTLS_PRIVATE(p) = (void *)trusted_block->key.n, - }; - const mbedtls_mpi e = { .MBEDTLS_PRIVATE(s) = 1, - .MBEDTLS_PRIVATE(n) = sizeof(trusted_block->key.e)/sizeof(mbedtls_mpi_uint), // 1 - .MBEDTLS_PRIVATE(p) = (void *)&trusted_block->key.e, - }; - mbedtls_rsa_init(&pk); - mbedtls_rsa_set_padding(&pk,MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); - ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e); + /* Convert e from uint32_t to byte array (big-endian) */ + uint8_t e_bytes[4]; + e_bytes[0] = (trusted_block->key.e >> 24) & 0xFF; + e_bytes[1] = (trusted_block->key.e >> 16) & 0xFF; + e_bytes[2] = (trusted_block->key.e >> 8) & 0xFF; + e_bytes[3] = trusted_block->key.e & 0xFF; + + ret = encode_rsa_pubkey_der( + n_be, rsa_key_size, + e_bytes, sizeof(e_bytes), + pubkey_der_buf, pubkey_der_buf_size, + &der_start, &der_len + ); + + free(n_be); + if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret); - goto exit_inner; + ESP_LOGE(TAG, "Failed to encode RSA public key to DER, err: %d", ret); + goto cleanup; } - ret = mbedtls_rsa_complete(&pk); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret); - goto exit_inner; - } + /* Set key attributes */ + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&key_attributes, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); - ret = mbedtls_rsa_check_pubkey(&pk); - if (ret != 0) { - ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret); - goto exit_inner; + /* Import DER-encoded public key into PSA */ + status = psa_import_key(&key_attributes, der_start, der_len, &key_id); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Failed to import key into PSA, err: %d", status); + ret = ESP_FAIL; + goto cleanup; } /* Signature needs to be byte swapped into BE representation */ @@ -78,24 +168,27 @@ esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_bloc sig_be[rsa_key_size - j - 1] = trusted_block->signature[j]; } - ret = mbedtls_rsa_public( &pk, sig_be, buf); - if (ret != 0) { - ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret); - goto exit_inner; - } + /* Verify the signature using PSA APIs */ + status = psa_verify_hash(key_id, PSA_ALG_RSA_PSS(PSA_ALG_SHA_256), + image_digest, ESP_SECURE_BOOT_DIGEST_LEN, + sig_be, rsa_key_size); - ret = mbedtls_rsa_rsassa_pss_verify( &pk, MBEDTLS_MD_SHA256, ESP_SECURE_BOOT_DIGEST_LEN, image_digest, sig_be); - if (ret != 0) { - ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Signature verification failed, err: %d", status); + ret = ESP_FAIL; } else { ESP_LOGI(TAG, "Signature verified successfully!"); + ret = ESP_OK; } -exit_inner: - mbedtls_rsa_free(&pk); -exit_outer: - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&entropy); + +cleanup: + /* Clean up resources */ + if (key_id != 0) { + psa_destroy_key(key_id); + } + psa_reset_key_attributes(&key_attributes); free(sig_be); - free(buf); + free(pubkey_der_buf); + return ret; } diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c index bdba167567b..2c7347a15b4 100644 --- a/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot_signatures_app.c @@ -11,12 +11,6 @@ #include "bootloader_signature.h" #include "esp_log.h" #include "esp_image_format.h" -#include "mbedtls/sha256.h" -#include "mbedtls/x509.h" -#include "mbedtls/md.h" -#include "mbedtls/platform.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" #include #include #include "esp_secure_boot.h"