mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-13 04:42:01 +03:00
feat(mbedtls): migrates ESP-TEE with PSA APIs
This commit is contained in:
@@ -5,15 +5,85 @@
|
||||
*/
|
||||
#include "esp_log.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
#include "mbedtls/asn1write.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 -1;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -23,8 +93,10 @@ esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_bloc
|
||||
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;
|
||||
}
|
||||
@@ -33,41 +105,47 @@ esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_bloc
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_id_t key_id = 0;
|
||||
|
||||
|
||||
/* Prepare the RSA public key data */
|
||||
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_pk_context pk;
|
||||
mbedtls_pk_init(&pk);
|
||||
|
||||
mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
|
||||
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(pk);
|
||||
|
||||
ret = mbedtls_rsa_import(rsa, &N, NULL, NULL, NULL, &e);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed to import RSA public key, err: %d", ret);
|
||||
mbedtls_pk_free(&pk);
|
||||
goto cleanup;
|
||||
}
|
||||
ret = mbedtls_rsa_complete(rsa);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed to complete RSA context, err: %d", ret);
|
||||
mbedtls_pk_free(&pk);
|
||||
goto cleanup;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
// Load the public key into PSA
|
||||
ret = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_HASH, &key_attributes);
|
||||
/* 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];
|
||||
}
|
||||
|
||||
/* 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 to get key attributes, err: %d", ret);
|
||||
mbedtls_pk_free(&pk);
|
||||
ESP_LOGE(TAG, "Failed to encode RSA public key to DER, err: %d", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -76,16 +154,14 @@ esp_err_t verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_bloc
|
||||
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_pk_import_into_psa(&pk, &key_attributes, &key_id);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed to import key into PSA, err: %d", ret);
|
||||
mbedtls_pk_free(&pk);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
mbedtls_rsa_free(rsa);
|
||||
mbedtls_pk_free(&pk);
|
||||
|
||||
/* Signature needs to be byte swapped into BE representation */
|
||||
for (int j = 0; j < rsa_key_size; j++) {
|
||||
sig_be[rsa_key_size - j - 1] = trusted_block->signature[j];
|
||||
@@ -111,6 +187,7 @@ cleanup:
|
||||
}
|
||||
psa_reset_key_attributes(&key_attributes);
|
||||
free(sig_be);
|
||||
free(pubkey_der_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user