From d7096313931fff186648dc1811ad8f654e580fc6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 12 Mar 2021 16:07:20 +1100 Subject: [PATCH] secure boot: Add boot check for SBV2 "check app signature on update" As this mode uses the public keys attached to the existing app's signatures to verify the next app, checking that a signature block is found on boot prevents the possibility of deploying a non-updatable device from the factory. --- .../include/esp_secure_boot.h | 28 +++++++++++++++++++ .../bootloader_support/src/secure_boot.c | 23 +++++++++++++++ .../secure_boot_signatures_app.c | 16 ++++++----- components/esp_system/startup.c | 17 +++++------ 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/components/bootloader_support/include/esp_secure_boot.h b/components/bootloader_support/include/esp_secure_boot.h index 9e132cd74a..94118c327c 100644 --- a/components/bootloader_support/include/esp_secure_boot.h +++ b/components/bootloader_support/include/esp_secure_boot.h @@ -243,6 +243,34 @@ typedef struct { */ void esp_secure_boot_init_checks(void); +#if !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME + +/** @brief Scan the current running app for signature blocks + * + * @note This function doesn't verify that the signatures are valid or the + * corresponding public keys are trusted, it only reads the number of signature + * blocks present and optionally calculates the digests of the public keys + * provided in the signature blocks. + * + * @param digest_public_keys If true, the key_digests fields in the + * public_key_digests structure will be filled with the digests of the public + * key provided in each signature block. Note that if Secure Boot V2 is enabled, + * each public key will only be trusted if the same digest is also present in + * eFuse (but this is not checked by this function). + * + * @param public_key_digests[out] Structure is initialized with the num_digests + * field set to the number of signatures found. If digest_public_keys is set, + * the public key digests are also calculated and stored here. + * + * @return + * - ESP_OK - At least one signature was found + * - ESP_ERR_NOT_FOUND - No signatures were found, num_digests value will be zero + * - ESP_FAIL - An error occured trying to read the signature blocks from flash + */ +esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests); + +#endif // !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/src/secure_boot.c b/components/bootloader_support/src/secure_boot.c index 42221501f1..9806b5c864 100644 --- a/components/bootloader_support/src/secure_boot.c +++ b/components/bootloader_support/src/secure_boot.c @@ -149,6 +149,23 @@ static esp_err_t secure_boot_v2_check(bool *need_fix) #endif #endif // CONFIG_SECURE_BOOT +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + +static void rsa_check_signature_on_update_check(void) +{ + // We rely on the keys used to sign this app to verify the next app on OTA, so make sure there is at + // least one to avoid a stuck firmware + esp_image_sig_public_key_digests_t digests = { 0 }; + + esp_err_t err = esp_secure_boot_get_signature_blocks_for_running_app(false, &digests); + + if (err != ESP_OK || digests.num_digests == 0) { + ESP_LOGE(TAG, "This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update."); + abort(); + } +} +#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + void esp_secure_boot_init_checks(void) { #ifdef CONFIG_SECURE_BOOT @@ -165,5 +182,11 @@ void esp_secure_boot_init_checks(void) ESP_LOGE(TAG, "Mismatch in secure boot settings: the app config is enabled but eFuse not"); } #endif // CONFIG_SECURE_BOOT + + +#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + rsa_check_signature_on_update_check(); +#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT + } #endif // not BOOTLOADER_BUILD 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 7497971537..d30e654dda 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 @@ -36,7 +36,6 @@ static const char *TAG = "secure_boot_v2"; #define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) -#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT /* A signature block is valid when it has correct magic byte, crc. */ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block) { @@ -47,7 +46,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo return ESP_OK; } -static esp_err_t get_signing_keys_for_running_app(esp_image_sig_public_key_digests_t *public_key_digests) +esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests) { esp_image_metadata_t metadata; const esp_partition_t* running_app_part = esp_ota_get_running_partition(); @@ -65,6 +64,8 @@ static esp_err_t get_signing_keys_for_running_app(esp_image_sig_public_key_diges return ESP_FAIL; } + memset(public_key_digests, 0, sizeof(esp_image_sig_public_key_digests_t)); + // Generating the SHA of the public key components in the signature block // metadata.image_len doesn't include any padding to start of the signature sector, so pad it here @@ -76,9 +77,11 @@ static esp_err_t get_signing_keys_for_running_app(esp_image_sig_public_key_diges esp_err_t err = bootloader_flash_read(addr, &block, sizeof(ets_secure_boot_sig_block_t), true); if (err == ESP_OK) { if (validate_signature_block(&block) == ESP_OK) { - bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); - bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key)); - bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]); + if (digest_public_keys) { + bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start(); + bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key)); + bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]); + } public_key_digests->num_digests++; } } else { @@ -92,14 +95,13 @@ static esp_err_t get_signing_keys_for_running_app(esp_image_sig_public_key_diges ESP_LOGE(TAG, "No signatures were found for the running app"); return ESP_ERR_NOT_FOUND; } -#endif // CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests) { #ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT // Gets key digests from running app ESP_LOGI(TAG, "Take trusted digest key(s) from running app"); - return get_signing_keys_for_running_app(public_key_digests); + return esp_secure_boot_get_signature_blocks_for_running_app(true, public_key_digests); #elif CONFIG_SECURE_BOOT_V2_ENABLED ESP_LOGI(TAG, "Take trusted digest key(s) from eFuse block(s)"); #if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index ebe2d985f9..4d398733dc 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -276,14 +276,6 @@ static void do_core_init(void) _REENT_SMALL_CHECK_INIT(_GLOBAL_REENT); #endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE) -#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED - esp_flash_encryption_init_checks(); -#endif - -#ifdef CONFIG_SECURE_BOOT - esp_secure_boot_init_checks(); -#endif - esp_err_t err __attribute__((unused)); #if CONFIG_SECURE_DISABLE_ROM_DL_MODE @@ -324,6 +316,15 @@ static void do_core_init(void) esp_err_t flash_ret = esp_flash_init_default_chip(); assert(flash_ret == ESP_OK); (void)flash_ret; + +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + esp_flash_encryption_init_checks(); +#endif + +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT) + // Note: in some configs this may read flash, so placed after flash init + esp_secure_boot_init_checks(); +#endif } static void do_secondary_init(void)