bootloader_support: Move secure boot code to bootloader_support
This commit is contained in:
parent
aceb6517c0
commit
98a0387854
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue