mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-18 23:54:39 +00:00
esp32c2: Support Secure Boot V2 based on ECDSA scheme
This commit is contained in:

committed by
Mahavir Jain

parent
dec3db6913
commit
2c725264f7
@@ -98,12 +98,20 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &block->ecdsa.key, sizeof(block->ecdsa.key));
|
||||
#endif
|
||||
bootloader_sha256_finish(sig_block_sha, key_digest);
|
||||
|
||||
// Check we can verify the image using this signature and this key
|
||||
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
bool verified = ets_ecdsa_verify(&block->ecdsa.key.point[0], block->ecdsa.signature, block->ecdsa.key.curve_id, image_digest, temp_verified_digest);
|
||||
#endif
|
||||
|
||||
if (!verified) {
|
||||
/* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
|
||||
|
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 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 "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"
|
||||
|
||||
static const char *TAG = "secure_boot_v2_ecdsa";
|
||||
|
||||
#define ECDSA_INTEGER_LEN 32
|
||||
|
||||
esp_err_t verify_ecdsa_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;
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
|
||||
mbedtls_mpi r, s;
|
||||
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
/* Initialise ECDSA context */
|
||||
mbedtls_ecdsa_context ecdsa_context;
|
||||
mbedtls_ecdsa_init(&ecdsa_context);
|
||||
|
||||
uint8_t key_size = 0;
|
||||
|
||||
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);
|
||||
break;
|
||||
case ECDSA_CURVE_P256:
|
||||
key_size = 32;
|
||||
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid curve ID");
|
||||
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] = {};
|
||||
|
||||
/* Convert r and s components 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];
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return ret;
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 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 "mbedtls/x509.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
|
||||
static const char *TAG = "secure_boot_v2_rsa";
|
||||
|
||||
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;
|
||||
const unsigned rsa_key_size = sizeof(sig_block->block[0].signature);
|
||||
unsigned char *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) {
|
||||
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\n", ret);
|
||||
goto exit_outer;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_complete(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_check_pubkey(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
/* 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];
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_public( &pk, sig_be, buf);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Signature verified successfully!");
|
||||
}
|
||||
exit_inner:
|
||||
mbedtls_rsa_free(&pk);
|
||||
exit_outer:
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
free(sig_be);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block);
|
||||
|
||||
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);
|
@@ -22,13 +22,15 @@
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
#include "secure_boot_signature_priv.h"
|
||||
|
||||
// Secure boot V2 for app
|
||||
|
||||
_Static_assert(SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == SECURE_BOOT_NUM_BLOCKS,
|
||||
"Parts of this code rely on the max number of signatures appended to an image"
|
||||
"being the same as the max number of trusted keys.");
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
@@ -76,7 +78,11 @@ esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_publi
|
||||
if (validate_signature_block(&block) == ESP_OK) {
|
||||
if (digest_public_keys) {
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key));
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &block.ecdsa.key, sizeof(block.ecdsa.key));
|
||||
#endif
|
||||
bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]);
|
||||
}
|
||||
public_key_digests->num_digests++;
|
||||
@@ -106,7 +112,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
|
||||
if (esp_secure_boot_read_key_digests(&efuse_trusted) == ESP_OK) {
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
if (efuse_trusted.key_digests[i] != NULL) {
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_KEY_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
}
|
||||
@@ -120,8 +126,8 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t digest[ESP_SECURE_BOOT_KEY_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_KEY_DIGEST_LEN] = {0};
|
||||
|
||||
/* Rounding off length to the upper 4k boundary */
|
||||
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
@@ -139,7 +145,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
|
||||
err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
@@ -150,13 +156,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
// This verify function is called only from app, during ota update.
|
||||
// This function is compiled in case when CONFIG_SECURE_BOOT_V2_ENABLED==y or CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT==y.
|
||||
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then FAIL (eFuse blocks should be set).
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
bool any_trusted_key = false;
|
||||
|
||||
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
|
||||
during boot-time verification. */
|
||||
memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
memset(verified_digest, 0, ESP_SECURE_BOOT_KEY_DIGEST_LEN);
|
||||
|
||||
esp_image_sig_public_key_digests_t trusted = {0};
|
||||
|
||||
@@ -165,26 +171,7 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
int ret = 0;
|
||||
mbedtls_rsa_context pk;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
const unsigned rsa_key_size = sizeof(sig_block->block[0].signature);
|
||||
unsigned char *sig_be = calloc(1, rsa_key_size);
|
||||
unsigned char *buf = calloc(1, rsa_key_size);
|
||||
if (sig_be == NULL || buf == NULL) {
|
||||
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\n", ret);
|
||||
goto exit_outer;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
const unsigned secure_boot_num_blocks = 1;
|
||||
#else
|
||||
@@ -202,12 +189,17 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
|
||||
/* Generate the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &app_blk->key, sizeof(app_blk->key));
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &app_blk->ecdsa.key, sizeof(app_blk->ecdsa.key));
|
||||
#endif
|
||||
|
||||
bootloader_sha256_finish(sig_block_sha, app_blk_digest);
|
||||
|
||||
/* Check if the key is one we trust */
|
||||
for (unsigned trusted_key_idx = 0; trusted_key_idx < secure_boot_num_blocks; trusted_key_idx++) {
|
||||
if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_DIGEST_LEN) == 0) {
|
||||
if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_KEY_DIGEST_LEN) == 0) {
|
||||
ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", app_blk_idx, trusted_key_idx);
|
||||
trusted_block = app_blk;
|
||||
any_trusted_key = true;
|
||||
@@ -220,63 +212,26 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
continue; // Skip the signature blocks with no trusted digest
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
|
||||
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);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_complete(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_check_pubkey(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
/* 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];
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_public( &pk, sig_be, buf);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
|
||||
goto exit_inner;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Signature verified successfully!");
|
||||
}
|
||||
exit_inner:
|
||||
mbedtls_rsa_free(&pk);
|
||||
ret = verify_rsa_signature_block(sig_block, image_digest, trusted_block);
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
ESP_LOGI(TAG, "Verifying with ECDSA...");
|
||||
ret = verify_ecdsa_signature_block(sig_block, image_digest, trusted_block);
|
||||
#endif
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit_outer:
|
||||
free(sig_be);
|
||||
free(buf);
|
||||
return (ret != 0 || any_trusted_key == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// To maintain backward compatibility
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
return esp_secure_boot_verify_sbv2_signature_block(sig_block, image_digest, verified_digest);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
// Secure boot V2 for bootloader.
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
static const char* TAG = "secure_boot_v2";
|
||||
|
||||
@@ -45,7 +45,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
|
||||
err = esp_secure_boot_verify_sbv2_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
@@ -83,7 +83,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
|
||||
if (err == ESP_OK) {
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
if (trusted_keys.key_digests[i] != NULL) {
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_KEY_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t
|
||||
|
||||
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then it is the first boot,
|
||||
// trusted.key_digests are filled from app sig_block.
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
esp_err_t esp_secure_boot_verify_sbv2_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
esp_image_sig_public_key_digests_t trusted = {0};
|
||||
bool efuse_keys_are_not_set = false;
|
||||
@@ -125,7 +125,11 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
// if efuse key digests are not in eFuse yet due to it is the first boot
|
||||
// then use digests from app to skip error in ets_secure_boot_verify_signature().
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].ecdsa.key, sizeof(sig_block->block[i].ecdsa.key));
|
||||
#endif
|
||||
bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]);
|
||||
}
|
||||
}
|
||||
@@ -133,19 +137,27 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
|
||||
#else
|
||||
ESP_LOGI(TAG, "Verifying with ECDSA...");
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest);
|
||||
#else
|
||||
ets_secure_boot_key_digests_t trusted_key_digests = {0};
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
|
||||
}
|
||||
|
||||
// Key revocation happens in ROM bootloader.
|
||||
// Do NOT allow key revocation while verifying application
|
||||
trusted_key_digests.allow_key_revoke = false;
|
||||
|
||||
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest);
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
if (sb_result != SB_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
@@ -154,4 +166,13 @@ esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signa
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// To maintain backward compatibility
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
return esp_secure_boot_verify_sbv2_signature_block(sig_block, image_digest, verified_digest);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
Reference in New Issue
Block a user