kopia lustrzana https://github.com/espressif/esp-idf
bootloader: Refactor secure boot digest generation
rodzic
1cab448c73
commit
f10cc7dc8e
|
@ -36,7 +36,6 @@ extern "C"
|
||||||
#define RTC_DATA_LOW 0x50000000
|
#define RTC_DATA_LOW 0x50000000
|
||||||
#define RTC_DATA_HIGH 0x50002000
|
#define RTC_DATA_HIGH 0x50002000
|
||||||
|
|
||||||
|
|
||||||
#define PART_TYPE_APP 0x00
|
#define PART_TYPE_APP 0x00
|
||||||
#define PART_SUBTYPE_FACTORY 0x00
|
#define PART_SUBTYPE_FACTORY 0x00
|
||||||
#define PART_SUBTYPE_OTA_FLAG 0x10
|
#define PART_SUBTYPE_OTA_FLAG 0x10
|
||||||
|
@ -66,8 +65,7 @@ void boot_cache_redirect( uint32_t pos, size_t size );
|
||||||
uint32_t get_bin_len(uint32_t pos);
|
uint32_t get_bin_len(uint32_t pos);
|
||||||
|
|
||||||
bool flash_encrypt(bootloader_state_t *bs);
|
bool flash_encrypt(bootloader_state_t *bs);
|
||||||
bool secure_boot(void);
|
bool secure_boot_generate_bootloader_digest(void);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,7 @@ void bootloader_main()
|
||||||
bootloader_state_t bs;
|
bootloader_state_t bs;
|
||||||
SpiFlashOpResult spiRet1,spiRet2;
|
SpiFlashOpResult spiRet1,spiRet2;
|
||||||
esp_ota_select_entry_t sa,sb;
|
esp_ota_select_entry_t sa,sb;
|
||||||
|
|
||||||
memset(&bs, 0, sizeof(bs));
|
memset(&bs, 0, sizeof(bs));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||||
|
@ -329,11 +330,15 @@ void bootloader_main()
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
|
ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos);
|
||||||
|
|
||||||
if(fhdr.secure_boot_flag == 0x01) {
|
if(fhdr.secure_boot_flag == 0x01) {
|
||||||
/* protect the 2nd_boot */
|
/* Generate secure digest from this bootloader to protect future
|
||||||
if(false == secure_boot()){
|
modifications */
|
||||||
ESP_LOGE(TAG, "secure boot failed");
|
if (secure_boot_generate_bootloader_digest() == false){
|
||||||
return;
|
ESP_LOGE(TAG, "Bootloader digest generation failed. SECURE BOOT IS NOT ENABLED.");
|
||||||
|
/* Allow booting to continue, as the failure is probably
|
||||||
|
due to user-configured EFUSEs for testing...
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ static const char* TAG = "secure_boot";
|
||||||
*
|
*
|
||||||
* @inputs: bool
|
* @inputs: bool
|
||||||
*/
|
*/
|
||||||
bool secure_boot_generate(uint32_t bin_len){
|
static bool secure_boot_generate(uint32_t bin_len){
|
||||||
SpiFlashOpResult spiRet;
|
SpiFlashOpResult spiRet;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
uint32_t buf[32];
|
uint32_t buf[32];
|
||||||
|
@ -87,41 +87,112 @@ bool secure_boot_generate(uint32_t bin_len){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Burn values written to the efuse write registers */
|
||||||
/**
|
static inline void burn_efuses()
|
||||||
* @function : secure_boot
|
{
|
||||||
* @description: protect boot code in flash
|
|
||||||
*
|
|
||||||
* @inputs: bool
|
|
||||||
*/
|
|
||||||
bool secure_boot(void){
|
|
||||||
uint32_t bin_len = 0;
|
|
||||||
if (REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "already secure boot !");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
boot_cache_redirect( 0, 64*1024);
|
|
||||||
bin_len = get_bin_len((uint32_t)MEM_CACHE(0x1000));
|
|
||||||
if (bin_len == 0) {
|
|
||||||
ESP_LOGE(TAG, "boot len is error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (false == secure_boot_generate(bin_len)){
|
|
||||||
ESP_LOGE(TAG, "secure boot generate failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
REG_SET_BIT(EFUSE_BLK0_WDATA6_REG, EFUSE_RD_ABS_DONE_0);
|
|
||||||
REG_WRITE(EFUSE_CONF_REG, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */
|
REG_WRITE(EFUSE_CONF_REG, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */
|
||||||
REG_WRITE(EFUSE_CMD_REG, 0x02); /* efuse_pgm_cmd */
|
REG_WRITE(EFUSE_CMD_REG, 0x02); /* efuse_pgm_cmd */
|
||||||
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_pagm_cmd=0 */
|
while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_pagm_cmd=0 */
|
||||||
ESP_LOGW(TAG, "burn abstract_done_0");
|
|
||||||
REG_WRITE(EFUSE_CONF_REG, 0x5AA5); /* efuse_read_op_ena, release force */
|
REG_WRITE(EFUSE_CONF_REG, 0x5AA5); /* efuse_read_op_ena, release force */
|
||||||
REG_WRITE(EFUSE_CMD_REG, 0x01); /* efuse_read_cmd */
|
REG_WRITE(EFUSE_CMD_REG, 0x01); /* efuse_read_cmd */
|
||||||
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_LOGI(TAG, "read EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
}
|
||||||
return true;
|
|
||||||
|
/**
|
||||||
|
* @function : secure_boot_generate_bootloader_digest
|
||||||
|
*
|
||||||
|
* @description: 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.)
|
||||||
|
*/
|
||||||
|
bool secure_boot_generate_bootloader_digest(void) {
|
||||||
|
uint32_t bin_len = 0;
|
||||||
|
if (REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boot_cache_redirect( 0, 64*1024);
|
||||||
|
bin_len = get_bin_len((uint32_t)MEM_CACHE(0x1000));
|
||||||
|
if (bin_len == 0) {
|
||||||
|
ESP_LOGE(TAG, "Invalid bootloader image length zero.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bin_len > 0x100000) {
|
||||||
|
ESP_LOGE(TAG, "Invalid bootloader image length %x", bin_len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
|
||||||
|
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
|
||||||
|
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
|
||||||
|
if (efuse_key_read_protected == false
|
||||||
|
&& efuse_key_write_protected == false
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA0_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA1_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA2_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA3_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA4_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA5_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA6_REG) == 0
|
||||||
|
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
|
||||||
|
ESP_LOGI(TAG, "Generating new secure boot key...");
|
||||||
|
/* reuse the secure boot IV generation function to generate
|
||||||
|
the key, as this generator uses the hardware RNG. */
|
||||||
|
uint32_t buf[32];
|
||||||
|
ets_secure_boot_rd_iv(buf);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
ESP_LOGV(TAG, "EFUSE_BLK2_WDATA%d_REG = 0x%08x", i, buf[i]);
|
||||||
|
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4*i, buf[i]);
|
||||||
|
}
|
||||||
|
bzero(buf, sizeof(buf));
|
||||||
|
burn_efuses();
|
||||||
|
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||||
|
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||||
|
burn_efuses();
|
||||||
|
efuse_key_read_protected = true;
|
||||||
|
efuse_key_write_protected = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Generating secure boot digest...");
|
||||||
|
if (false == secure_boot_generate(bin_len)){
|
||||||
|
ESP_LOGE(TAG, "secure boot generation failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (!efuse_key_write_protected) {
|
||||||
|
ESP_LOGE(TAG, "Pre-loaded key is not write protected. Refusing to blow secure boot efuse.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "blowing secure boot efuse & disabling JTAG...");
|
||||||
|
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||||
|
REG_WRITE(EFUSE_BLK0_WDATA6_REG,
|
||||||
|
EFUSE_RD_ABS_DONE_0 | EFUSE_RD_DISABLE_JTAG);
|
||||||
|
burn_efuses();
|
||||||
|
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "secure boot not enabled for bootloader image, EFUSE_RD_ABS_DONE_0 is probably write protected!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue