bootloader_support: Move secure boot code to bootloader_support

This commit is contained in:
Angus Gratton 2016-11-02 17:54:47 +11:00
parent aceb6517c0
commit 98a0387854
5 changed files with 85 additions and 82 deletions

View file

@ -60,7 +60,6 @@ typedef struct {
} bootloader_state_t; } bootloader_state_t;
bool flash_encrypt(bootloader_state_t *bs); bool flash_encrypt(bootloader_state_t *bs);
bool secure_boot_generate_bootloader_digest(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -34,6 +34,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_image_format.h" #include "esp_image_format.h"
#include "esp_secure_boot.h"
#include "bootloader_flash.h" #include "bootloader_flash.h"
#include "bootloader_config.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_LOGI(TAG, "Espressif ESP32 2nd stage bootloader v. %s", BOOT_VERSION);
esp_err_t err;
esp_image_header_t fhdr; esp_image_header_t fhdr;
bootloader_state_t bs; bootloader_state_t bs;
SpiFlashOpResult spiRet1,spiRet2; SpiFlashOpResult spiRet1,spiRet2;
@ -308,8 +310,9 @@ void bootloader_main()
if(fhdr.secure_boot_flag == 0x01) { if(fhdr.secure_boot_flag == 0x01) {
/* Generate secure digest from this bootloader to protect future /* Generate secure digest from this bootloader to protect future
modifications */ modifications */
if (secure_boot_generate_bootloader_digest() == false){ err = esp_secure_boot_permanently_enable();
ESP_LOGE(TAG, "Bootloader digest generation failed. SECURE BOOT IS NOT ENABLED."); 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 /* Allow booting to continue, as the failure is probably
due to user-configured EFUSEs for testing... due to user-configured EFUSEs for testing...
*/ */

View file

@ -16,6 +16,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <esp_err.h> #include <esp_err.h>
#include "soc/efuse_reg.h"
/* Support functions for secure boot features. /* Support functions for secure boot features.
@ -30,21 +31,34 @@
* *
* @return true if secure boot is enabled. * @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. * 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 * @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
* secure boot to be enabled cleanly. ESP_OK if secure boot * secure boot to be enabled cleanly. ESP_OK if secure boot
* is enabled on this chip from now on. * 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);

View file

@ -30,72 +30,81 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#include "bootloader_config.h"
#include "bootloader_flash.h" #include "bootloader_flash.h"
#include "esp_image_format.h" #include "esp_image_format.h"
#include "esp_secure_boot.h"
static const char* TAG = "secure_boot"; 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 * @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){ static bool secure_boot_generate(uint32_t image_len){
SpiFlashOpResult spiRet; SpiFlashOpResult spiRet;
uint32_t buf[32]; /* buffer is uint32_t not uint8_t to meet ROM SPI API signature */
uint32_t buf[IV_LEN / sizeof(uint32_t)];
const void *image; const void *image;
if (image_len % 128 != 0) { /* hardware secure boot engine only takes full blocks, so round up the
image_len = (image_len / 128 + 1) * 128; image length. The additional data should all be 0xFF.
} */
ets_secure_boot_start(); if (image_len % HASH_BLOCK_SIZE != 0) {
ets_secure_boot_rd_iv(buf); image_len = (image_len / HASH_BLOCK_SIZE + 1) * HASH_BLOCK_SIZE;
ets_secure_boot_hash(NULL); }
Cache_Read_Disable(0); ets_secure_boot_start();
/* iv stored in sec 0 */ ets_secure_boot_rd_iv(buf);
spiRet = SPIEraseSector(0); ets_secure_boot_hash(NULL);
if (spiRet != SPI_FLASH_RESULT_OK) Cache_Read_Disable(0);
{ /* iv stored in sec 0 */
ESP_LOGE(TAG, SPI_ERROR_LOG); spiRet = SPIEraseSector(0);
return false; if (spiRet != SPI_FLASH_RESULT_OK)
} {
Cache_Read_Enable(0); 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."); ESP_LOGD(TAG, "write iv to flash.");
spiRet = SPIWrite(0, buf, 128); spiRet = SPIWrite(0, buf, IV_LEN);
if (spiRet != SPI_FLASH_RESULT_OK) if (spiRet != SPI_FLASH_RESULT_OK)
{ {
ESP_LOGE(TAG, SPI_ERROR_LOG); ESP_LOGE(TAG, "SPI write failed %d", spiRet);
return false; return false;
} }
bzero(buf, sizeof(buf));
/* generate digest from image contents */ /* generate digest from image contents */
image = bootloader_mmap(0x1000, image_len); image = bootloader_mmap(0x1000, image_len);
if (!image) { if (!image) {
ESP_LOGE(TAG, "bootloader_mmap(0x1000, 0x%x) failed", image_len); ESP_LOGE(TAG, "bootloader_mmap(0x1000, 0x%x) failed", image_len);
return false; return false;
} }
for (int i = 0; i < image_len; i+=128) { for (int i = 0; i < image_len; i+= HASH_BLOCK_SIZE) {
ets_secure_boot_hash(image + i/sizeof(void *)); ets_secure_boot_hash(image + i/sizeof(void *));
} }
bootloader_unmap(image); bootloader_unmap(image);
ets_secure_boot_obtain(); ets_secure_boot_obtain();
ets_secure_boot_rd_abstract(buf); ets_secure_boot_rd_abstract(buf);
ets_secure_boot_finish(); ets_secure_boot_finish();
ESP_LOGD(TAG, "write abstract to flash."); ESP_LOGD(TAG, "write digest to flash.");
spiRet = SPIWrite(0x80, buf, 64); spiRet = SPIWrite(0x80, buf, DIGEST_LEN);
if (spiRet != SPI_FLASH_RESULT_OK) { if (spiRet != SPI_FLASH_RESULT_OK) {
ESP_LOGE(TAG, SPI_ERROR_LOG); ESP_LOGE(TAG, "SPI write failed %d", spiRet);
return false; return false;
} }
ESP_LOGD(TAG, "write abstract to flash."); ESP_LOGD(TAG, "write digest to flash.");
Cache_Read_Enable(0); Cache_Read_Enable(0);
return true; return true;
} }
/* Burn values written to the efuse write registers */ /* 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 */ while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_read_cmd=0 */
} }
/** esp_err_t esp_secure_boot_permanently_enable(void) {
* @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 err; esp_err_t err;
uint32_t image_len = 0; 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.."); ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
return true; return ESP_OK;
} }
err = esp_image_basic_verify(0x1000, &image_len); err = esp_image_basic_verify(0x1000, &image_len);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", err); ESP_LOGE(TAG, "bootloader image appears invalid! error %d", err);
return false; return err;
} }
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG); 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..."); ESP_LOGI(TAG, "Generating secure boot digest...");
if (false == secure_boot_generate(image_len)){ if (false == secure_boot_generate(image_len)){
ESP_LOGE(TAG, "secure boot generation failed"); ESP_LOGE(TAG, "secure boot generation failed");
return false; return ESP_FAIL;
} }
ESP_LOGI(TAG, "Digest generation complete."); ESP_LOGI(TAG, "Digest generation complete.");
if (!efuse_key_read_protected) { if (!efuse_key_read_protected) {
ESP_LOGE(TAG, "Pre-loaded key is not read protected. Refusing to blow secure boot efuse."); 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) { if (!efuse_key_write_protected) {
ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse."); 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..."); 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); ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after);
if (after & EFUSE_RD_ABS_DONE_0) { if (after & EFUSE_RD_ABS_DONE_0) {
ESP_LOGI(TAG, "secure boot is now enabled for bootloader image"); ESP_LOGI(TAG, "secure boot is now enabled for bootloader image");
return true; return ESP_OK;
} else { } else {
ESP_LOGE(TAG, "secure boot not enabled for bootloader image, EFUSE_RD_ABS_DONE_0 is probably write protected!"); 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;
} }
} }

View file

@ -1,7 +0,0 @@
#include <stdint.h>
#include <limits.h>
#include "esp_log.h"