From 98a0387854918b73d10e00820e40a36786ee8eab Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 2 Nov 2016 17:54:47 +1100 Subject: [PATCH] bootloader_support: Move secure boot code to bootloader_support --- .../bootloader/src/main/bootloader_config.h | 1 - .../bootloader/src/main/bootloader_start.c | 7 +- .../{esp_secureboot.h => esp_secure_boot.h} | 24 +++- .../src}/secure_boot.c | 128 +++++++++--------- .../bootloader_support/src/secureboot.c | 7 - 5 files changed, 85 insertions(+), 82 deletions(-) rename components/bootloader_support/include/{esp_secureboot.h => esp_secure_boot.h} (64%) rename components/{bootloader/src/main => bootloader_support/src}/secure_boot.c (71%) delete mode 100644 components/bootloader_support/src/secureboot.c diff --git a/components/bootloader/src/main/bootloader_config.h b/components/bootloader/src/main/bootloader_config.h index 0823581824..4559d5f816 100644 --- a/components/bootloader/src/main/bootloader_config.h +++ b/components/bootloader/src/main/bootloader_config.h @@ -60,7 +60,6 @@ typedef struct { } bootloader_state_t; bool flash_encrypt(bootloader_state_t *bs); -bool secure_boot_generate_bootloader_digest(void); #ifdef __cplusplus } diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index 3bc2696a4b..59b180fd84 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -34,6 +34,7 @@ #include "sdkconfig.h" #include "esp_image_format.h" +#include "esp_secure_boot.h" #include "bootloader_flash.h" #include "bootloader_config.h" @@ -214,6 +215,7 @@ void bootloader_main() { ESP_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION); + esp_err_t err; esp_image_header_t fhdr; bootloader_state_t bs; SpiFlashOpResult spiRet1,spiRet2; @@ -308,8 +310,9 @@ void bootloader_main() if(fhdr.secure_boot_flag == 0x01) { /* Generate secure digest from this bootloader to protect future modifications */ - if (secure_boot_generate_bootloader_digest() == false){ - ESP_LOGE(TAG, "Bootloader digest generation failed. SECURE BOOT IS NOT ENABLED."); + err = esp_secure_boot_permanently_enable(); + if (err != ESP_OK){ + ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err); /* Allow booting to continue, as the failure is probably due to user-configured EFUSEs for testing... */ diff --git a/components/bootloader_support/include/esp_secureboot.h b/components/bootloader_support/include/esp_secure_boot.h similarity index 64% rename from components/bootloader_support/include/esp_secureboot.h rename to components/bootloader_support/include/esp_secure_boot.h index b0097df8a6..4bf2dc8b23 100644 --- a/components/bootloader_support/include/esp_secureboot.h +++ b/components/bootloader_support/include/esp_secure_boot.h @@ -16,6 +16,7 @@ #include #include +#include "soc/efuse_reg.h" /* Support functions for secure boot features. @@ -30,21 +31,34 @@ * * @return true if secure boot is enabled. */ -bool esp_secure_boot_enabled(void); +static inline bool esp_secure_boot_enabled(void) { + return REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_RD_ABS_DONE_0); +} -/** @brief Enable secure boot if it isw not already enabled. +/** @brief Enable secure boot if it is not already enabled. * - * @important If this function succeeds, secure boot is permanentl + * @important If this function succeeds, secure boot is permanently * enabled on the chip via efuse. * - * This function is intended to be called from bootloader code. + * @important This function is intended to be called from bootloader code only. + * + * If secure boot is not yet enabled for bootloader, this will + * generate the secure boot digest and enable secure boot by blowing + * the EFUSE_RD_ABS_DONE_0 efuse. + * + * This function does not verify secure boot of the bootloader (the + * ROM bootloader does this.) + * + * Will fail if efuses have been part-burned in a way that indicates + * secure boot should not or could not be correctly enabled. + * * * @return ESP_ERR_INVALID_STATE if efuse state doesn't allow * secure boot to be enabled cleanly. ESP_OK if secure boot * is enabled on this chip from now on. */ -esp_err_t esp_secure_boot_enable(void); +esp_err_t esp_secure_boot_permanently_enable(void); diff --git a/components/bootloader/src/main/secure_boot.c b/components/bootloader_support/src/secure_boot.c similarity index 71% rename from components/bootloader/src/main/secure_boot.c rename to components/bootloader_support/src/secure_boot.c index 2b1b8573fc..c17aebfbea 100644 --- a/components/bootloader/src/main/secure_boot.c +++ b/components/bootloader_support/src/secure_boot.c @@ -30,72 +30,81 @@ #include "sdkconfig.h" -#include "bootloader_config.h" #include "bootloader_flash.h" #include "esp_image_format.h" +#include "esp_secure_boot.h" static const char* TAG = "secure_boot"; +#define HASH_BLOCK_SIZE 128 +#define IV_LEN HASH_BLOCK_SIZE +#define DIGEST_LEN 64 + /** * @function : secure_boot_generate - * @description: generate boot abstract & iv + * @description: generate boot digest (aka "abstract") & iv * - * @inputs: bool + * @inputs: image_len - length of image to calculate digest for */ static bool secure_boot_generate(uint32_t image_len){ - SpiFlashOpResult spiRet; - uint32_t buf[32]; + SpiFlashOpResult spiRet; + /* buffer is uint32_t not uint8_t to meet ROM SPI API signature */ + uint32_t buf[IV_LEN / sizeof(uint32_t)]; const void *image; - if (image_len % 128 != 0) { - image_len = (image_len / 128 + 1) * 128; - } - ets_secure_boot_start(); - ets_secure_boot_rd_iv(buf); - ets_secure_boot_hash(NULL); - Cache_Read_Disable(0); - /* iv stored in sec 0 */ - spiRet = SPIEraseSector(0); - if (spiRet != SPI_FLASH_RESULT_OK) - { - ESP_LOGE(TAG, SPI_ERROR_LOG); - return false; - } - Cache_Read_Enable(0); + /* hardware secure boot engine only takes full blocks, so round up the + image length. The additional data should all be 0xFF. + */ + if (image_len % HASH_BLOCK_SIZE != 0) { + image_len = (image_len / HASH_BLOCK_SIZE + 1) * HASH_BLOCK_SIZE; + } + ets_secure_boot_start(); + ets_secure_boot_rd_iv(buf); + ets_secure_boot_hash(NULL); + Cache_Read_Disable(0); + /* iv stored in sec 0 */ + spiRet = SPIEraseSector(0); + if (spiRet != SPI_FLASH_RESULT_OK) + { + ESP_LOGE(TAG, "SPI erase failed %d", spiRet); + return false; + } + Cache_Read_Enable(0); - /* write iv to flash, 0x0000, 128 bytes (1024 bits) */ + /* write iv to flash, 0x0000, 128 bytes (1024 bits) */ ESP_LOGD(TAG, "write iv to flash."); - spiRet = SPIWrite(0, buf, 128); - if (spiRet != SPI_FLASH_RESULT_OK) - { - ESP_LOGE(TAG, SPI_ERROR_LOG); - return false; - } + spiRet = SPIWrite(0, buf, IV_LEN); + if (spiRet != SPI_FLASH_RESULT_OK) + { + ESP_LOGE(TAG, "SPI write failed %d", spiRet); + return false; + } + bzero(buf, sizeof(buf)); - /* generate digest from image contents */ + /* generate digest from image contents */ image = bootloader_mmap(0x1000, image_len); if (!image) { ESP_LOGE(TAG, "bootloader_mmap(0x1000, 0x%x) failed", image_len); return false; } - for (int i = 0; i < image_len; i+=128) { - ets_secure_boot_hash(image + i/sizeof(void *)); - } + for (int i = 0; i < image_len; i+= HASH_BLOCK_SIZE) { + ets_secure_boot_hash(image + i/sizeof(void *)); + } bootloader_unmap(image); - ets_secure_boot_obtain(); - ets_secure_boot_rd_abstract(buf); - ets_secure_boot_finish(); + ets_secure_boot_obtain(); + ets_secure_boot_rd_abstract(buf); + ets_secure_boot_finish(); - ESP_LOGD(TAG, "write abstract to flash."); - spiRet = SPIWrite(0x80, buf, 64); - if (spiRet != SPI_FLASH_RESULT_OK) { - ESP_LOGE(TAG, SPI_ERROR_LOG); - return false; - } - ESP_LOGD(TAG, "write abstract to flash."); - Cache_Read_Enable(0); - return true; + ESP_LOGD(TAG, "write digest to flash."); + spiRet = SPIWrite(0x80, buf, DIGEST_LEN); + if (spiRet != SPI_FLASH_RESULT_OK) { + ESP_LOGE(TAG, "SPI write failed %d", spiRet); + return false; + } + ESP_LOGD(TAG, "write digest to flash."); + Cache_Read_Enable(0); + return true; } /* Burn values written to the efuse write registers */ @@ -109,34 +118,19 @@ static inline void burn_efuses() while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_read_cmd=0 */ } -/** - * @brief Enable secure boot if it is not already enabled. - * - * Called if the secure boot flag is set on the - * bootloader image in flash. If secure boot is not yet enabled for - * bootloader, this will generate the secure boot digest and enable - * secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse. - * - * This function does not verify secure boot of the bootloader (the - * ROM bootloader does this.) - * - * @return true if secure boot is enabled (either was already enabled, - * or is freshly enabled as a result of calling this function.) false - * implies an error occured (possibly secure boot is part-enabled.) - */ -bool secure_boot_generate_bootloader_digest(void) { +esp_err_t esp_secure_boot_permanently_enable(void) { esp_err_t err; uint32_t image_len = 0; - if (REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0) + if (esp_secure_boot_enabled()) { ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing.."); - return true; + return ESP_OK; } err = esp_image_basic_verify(0x1000, &image_len); if (err != ESP_OK) { ESP_LOGE(TAG, "bootloader image appears invalid! error %d", err); - return false; + return err; } uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG); @@ -178,17 +172,17 @@ bool secure_boot_generate_bootloader_digest(void) { ESP_LOGI(TAG, "Generating secure boot digest..."); if (false == secure_boot_generate(image_len)){ ESP_LOGE(TAG, "secure boot generation failed"); - return false; + return ESP_FAIL; } ESP_LOGI(TAG, "Digest generation complete."); if (!efuse_key_read_protected) { ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse."); - return false; + return ESP_ERR_INVALID_STATE; } if (!efuse_key_write_protected) { ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse."); - return false; + return ESP_ERR_INVALID_STATE; } ESP_LOGI(TAG, "blowing secure boot efuse & disabling JTAG..."); @@ -200,9 +194,9 @@ bool secure_boot_generate_bootloader_digest(void) { ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after); if (after & EFUSE_RD_ABS_DONE_0) { ESP_LOGI(TAG, "secure boot is now enabled for bootloader image"); - return true; + return ESP_OK; } else { ESP_LOGE(TAG, "secure boot not enabled for bootloader image, EFUSE_RD_ABS_DONE_0 is probably write protected!"); - return false; + return ESP_ERR_INVALID_STATE; } } diff --git a/components/bootloader_support/src/secureboot.c b/components/bootloader_support/src/secureboot.c deleted file mode 100644 index e55c1f33fa..0000000000 --- a/components/bootloader_support/src/secureboot.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -#include "esp_log.h" - - -