From: Angus Gratton Date: Tue, 25 Oct 2016 03:55:35 +0000 (+1100) Subject: bootloader: Refactor secure boot digest generation X-Git-Tag: v1.0~62^2~18 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f10cc7dc8eb09bcdd3075b7f8ef9303e3dc3da28;p=esp-idf bootloader: Refactor secure boot digest generation --- diff --git a/components/bootloader/src/main/bootloader_config.h b/components/bootloader/src/main/bootloader_config.h index 8a837693c2..1655280dc7 100644 --- a/components/bootloader/src/main/bootloader_config.h +++ b/components/bootloader/src/main/bootloader_config.h @@ -36,7 +36,6 @@ extern "C" #define RTC_DATA_LOW 0x50000000 #define RTC_DATA_HIGH 0x50002000 - #define PART_TYPE_APP 0x00 #define PART_SUBTYPE_FACTORY 0x00 #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); bool flash_encrypt(bootloader_state_t *bs); -bool secure_boot(void); - +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 5b1e152070..a4b27702c4 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -256,6 +256,7 @@ void bootloader_main() bootloader_state_t bs; SpiFlashOpResult spiRet1,spiRet2; esp_ota_select_entry_t sa,sb; + memset(&bs, 0, sizeof(bs)); ESP_LOGI(TAG, "compile time " __TIME__ ); @@ -329,16 +330,20 @@ void bootloader_main() } ESP_LOGI(TAG, "Loading app partition at offset %08x", load_part_pos); + if(fhdr.secure_boot_flag == 0x01) { - /* protect the 2nd_boot */ - if(false == secure_boot()){ - ESP_LOGE(TAG, "secure boot failed"); - return; + /* 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."); + /* Allow booting to continue, as the failure is probably + due to user-configured EFUSEs for testing... + */ } } if(fhdr.encrypt_flag == 0x01) { - /* encrypt flash */ + /* encrypt flash */ if (false == flash_encrypt(&bs)) { ESP_LOGE(TAG, "flash encrypt failed"); return; diff --git a/components/bootloader/src/main/secure_boot.c b/components/bootloader/src/main/secure_boot.c index 3dfdbd1412..9247f2cbd9 100644 --- a/components/bootloader/src/main/secure_boot.c +++ b/components/bootloader/src/main/secure_boot.c @@ -40,7 +40,7 @@ static const char* TAG = "secure_boot"; * * @inputs: bool */ -bool secure_boot_generate(uint32_t bin_len){ +static bool secure_boot_generate(uint32_t bin_len){ SpiFlashOpResult spiRet; uint16_t i; uint32_t buf[32]; @@ -87,41 +87,112 @@ bool secure_boot_generate(uint32_t bin_len){ return true; } +/* Burn values written to the efuse write registers */ +static inline void burn_efuses() +{ + REG_WRITE(EFUSE_CONF_REG, 0x5A5A); /* efuse_pgm_op_ena, force no rd/wr disable */ + REG_WRITE(EFUSE_CMD_REG, 0x02); /* efuse_pgm_cmd */ + while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_pagm_cmd=0 */ + REG_WRITE(EFUSE_CONF_REG, 0x5AA5); /* efuse_read_op_ena, release force */ + REG_WRITE(EFUSE_CMD_REG, 0x01); /* efuse_read_cmd */ + while (REG_READ(EFUSE_CMD_REG)); /* wait for efuse_read_cmd=0 */ +} /** - * @function : secure_boot - * @description: protect boot code in flash + * @function : secure_boot_generate_bootloader_digest * - * @inputs: bool + * @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(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_CMD_REG, 0x02); /* efuse_pgm_cmd */ - 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_CMD_REG, 0x01); /* efuse_read_cmd */ - 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; +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; + } }