feat: migrates bootloader_support to PSA APIs

This commit is contained in:
Ashish Sharma
2025-12-23 10:25:13 +08:00
committed by Mahavir Jain
parent dbd198a97e
commit eb95eafac1
6 changed files with 312 additions and 191 deletions

View File

@@ -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 <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
#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 */

View File

@@ -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 <string.h>
#include <sys/param.h>
#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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 <string.h>
#include <sys/param.h>
#include "esp_secure_boot.h"