bootloader: Support Flash Encryption for ESP32-C2

This commit is contained in:
KonstantinKondrashov
2022-05-04 19:04:56 +08:00
committed by BOT
parent d11af9051b
commit 505e18237a
17 changed files with 293 additions and 93 deletions
@@ -577,6 +577,17 @@ static void load_image(const esp_image_metadata_t *image_data)
esp_err_t err;
#endif
#ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
if (esp_secure_boot_enabled() ^ esp_flash_encrypt_initialized_once()) {
ESP_LOGE(TAG, "Secure Boot and Flash Encryption cannot be enabled separately, only together (their keys go into one eFuse key block)");
return;
}
if (!esp_secure_boot_enabled() || !esp_flash_encryption_enabled()) {
esp_efuse_batch_write_begin();
}
#endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
#ifdef CONFIG_SECURE_BOOT_V2_ENABLED
err = esp_secure_boot_v2_permanently_enable(image_data);
if (err != ESP_OK) {
@@ -604,13 +615,50 @@ static void load_image(const esp_image_metadata_t *image_data)
* 5) Burn EFUSE to enable flash encryption
*/
ESP_LOGI(TAG, "Checking flash encryption...");
bool flash_encryption_enabled = esp_flash_encryption_enabled();
err = esp_flash_encrypt_check_and_update();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
bool flash_encryption_enabled = esp_flash_encrypt_state();
if (!flash_encryption_enabled) {
#ifdef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED is set, refusing to boot.");
return;
#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
if (esp_flash_encrypt_is_write_protected(true)) {
return;
}
err = esp_flash_encrypt_init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Initialization of Flash Encryption key failed (%d)", err);
return;
}
}
#endif
#ifdef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
if (!esp_secure_boot_enabled() || !flash_encryption_enabled) {
err = esp_efuse_batch_write_commit();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error programming eFuses (err=0x%x).", err);
return;
}
assert(esp_secure_boot_enabled());
ESP_LOGI(TAG, "Secure boot permanently enabled");
}
#endif // CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
if (!flash_encryption_enabled) {
err = esp_flash_encrypt_contents();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Encryption flash contents failed (%d)", err);
return;
}
err = esp_flash_encrypt_enable();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Enabling of Flash encryption failed (%d)", err);
return;
}
}
#endif // CONFIG_SECURE_FLASH_ENC_ENABLED
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
/* Step 6 (see above for full description):
@@ -23,7 +23,12 @@ esp_err_t esp_flash_encryption_enable_secure_features(void)
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
#endif
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
ESP_LOGI(TAG, "Disable UART bootloader cache...");
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
#else
ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
#endif
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
ESP_LOGI(TAG, "Disable JTAG...");
@@ -47,10 +47,10 @@ void esp_flash_encryption_init_checks()
if (flash_crypt_cnt == (1<<(CRYPT_CNT[0]->bit_count))-1) {
// If encryption counter is already max, no need to write protect it
// (this distinction is important on ESP32 ECO3 where write-procted FLASH_CRYPT_CNT also write-protects UART_DL_DIS)
return;
} else {
ESP_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
esp_flash_write_protect_crypt_cnt();
}
ESP_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
esp_flash_write_protect_crypt_cnt();
}
}
#endif // CONFIG_SECURE_BOOT
@@ -110,17 +110,6 @@ void esp_flash_write_protect_crypt_cnt(void)
esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
{
bool flash_crypt_cnt_wr_dis = false;
#if CONFIG_IDF_TARGET_ESP32
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
uint8_t dis_dl_enc = 0;
uint8_t dis_dl_icache = 0;
uint8_t dis_dl_dcache = 0;
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
uint8_t dis_dl_enc = 0;
uint8_t dis_dl_icache = 0;
#endif
esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
if (esp_flash_encryption_enabled()) {
@@ -138,27 +127,32 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
if (flash_crypt_cnt_wr_dis) {
#if CONFIG_IDF_TARGET_ESP32
dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
bool dis_dl_cache = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_CACHE);
bool dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT);
bool dis_dl_dec = esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_DECRYPT);
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
mode = ESP_FLASH_ENC_MODE_RELEASE;
}
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
dis_dl_dcache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
bool dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
bool dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
bool dis_dl_dcache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
mode = ESP_FLASH_ENC_MODE_RELEASE;
}
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
bool dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
bool dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
if (dis_dl_enc && dis_dl_icache) {
mode = ESP_FLASH_ENC_MODE_RELEASE;
#ifdef CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
// This chip supports two types of key: AES128_DERIVED and AES128.
// To be in RELEASE mode, it is important for the AES128_DERIVED key that XTS_KEY_LENGTH_256 be write-protected.
bool xts_key_len_256_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
mode = (xts_key_len_256_wr_dis) ? ESP_FLASH_ENC_MODE_RELEASE : ESP_FLASH_ENC_MODE_DEVELOPMENT;
#endif // CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
}
#endif
}
@@ -197,9 +191,15 @@ void esp_flash_encryption_set_release_mode(void)
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
#elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
#ifdef CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
// For AES128_DERIVED, FE key is 16 bytes and XTS_KEY_LENGTH_256 is 0.
// It is important to protect XTS_KEY_LENGTH_256 from further changing it to 1. Set write protection for this bit.
// Burning WR_DIS_CRYPT_CNT, blocks further changing of eFuses: DIS_DOWNLOAD_MANUAL_ENCRYPT, SPI_BOOT_CRYPT_CNT, [XTS_KEY_LENGTH_256], SECURE_BOOT_EN.
esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT);
#endif // CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED
#else
ESP_LOGE(TAG, "Flash Encryption support not added, abort..");
abort();
@@ -15,9 +15,8 @@
#include "esp_efuse_table.h"
#include "esp_log.h"
#include "hal/wdt_hal.h"
#ifdef CONFIG_IDF_TARGET_ESP32C2
// IDF-3899
#warning "Not support flash encryption on esp32c2 yet."
#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
#include "soc/sensitive_reg.h"
#endif
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
@@ -30,6 +29,8 @@
#define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
#endif
#define FLASH_ENC_CNT_MAX (CRYPT_CNT[0]->bit_count)
/* This file implements FLASH ENCRYPTION related APIs to perform
* various operations such as programming necessary flash encryption
* eFuses, detect whether flash encryption is enabled (by reading eFuse)
@@ -39,38 +40,86 @@
static const char *TAG = "flash_encrypt";
/* Static functions for stages of flash encryption */
static esp_err_t initialise_flash_encryption(void);
static esp_err_t encrypt_flash_contents(size_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
static esp_err_t encrypt_bootloader(void);
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
static size_t get_flash_encrypt_cnt_value(void);
esp_err_t esp_flash_encrypt_check_and_update(void)
static size_t get_flash_encrypt_cnt_value(void)
{
size_t flash_crypt_cnt = 0;
esp_efuse_read_field_cnt(CRYPT_CNT, &flash_crypt_cnt);
bool flash_crypt_wr_dis = esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT);
return flash_crypt_cnt;
}
bool esp_flash_encrypt_initialized_once(void)
{
return get_flash_encrypt_cnt_value() != 0;
}
bool esp_flash_encrypt_is_write_protected(bool print_error)
{
if (esp_efuse_read_field_bit(WR_DIS_CRYPT_CNT)) {
if (print_error) {
ESP_LOGE(TAG, "Flash Encryption cannot be enabled (CRYPT_CNT (%d) is write protected)", get_flash_encrypt_cnt_value());
}
return true;
}
return false;
}
bool esp_flash_encrypt_state(void)
{
size_t flash_crypt_cnt = get_flash_encrypt_cnt_value();
bool flash_crypt_wr_dis = esp_flash_encrypt_is_write_protected(false);
ESP_LOGV(TAG, "CRYPT_CNT %d, write protection %d", flash_crypt_cnt, flash_crypt_wr_dis);
if (flash_crypt_cnt % 2 == 1) {
/* Flash is already encrypted */
int left = (CRYPT_CNT[0]->bit_count - flash_crypt_cnt) / 2;
int left = (FLASH_ENC_CNT_MAX - flash_crypt_cnt) / 2;
if (flash_crypt_wr_dis) {
left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */
}
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
return ESP_OK;
} else {
return true;
}
return false;
}
esp_err_t esp_flash_encrypt_check_and_update(void)
{
bool flash_encryption_enabled = esp_flash_encrypt_state();
if (!flash_encryption_enabled) {
#ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
/* Flash is not encrypted, so encrypt it! */
return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
if (esp_flash_encrypt_is_write_protected(true)) {
return ESP_FAIL;
}
esp_err_t err = esp_flash_encrypt_init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Initialization of Flash encryption key failed (%d)", err);
return err;
}
err = esp_flash_encrypt_contents();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Encryption flash contents failed (%d)", err);
return err;
}
err = esp_flash_encrypt_enable();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Enabling of Flash encryption failed (%d)", err);
return err;
}
#else
ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED "
"is set, refusing to boot.");
return ESP_ERR_INVALID_STATE;
#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
}
return ESP_OK;
}
static esp_err_t check_and_generate_encryption_keys(void)
@@ -101,10 +150,10 @@ static esp_err_t check_and_generate_encryption_keys(void)
return ESP_ERR_INVALID_STATE;
}
#else
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES64
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES128_DERIVED
enum { BLOCKS_NEEDED = 1 };
esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = {
ESP_EFUSE_KEY_PURPOSE_XTS_AES_64_KEY,
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY_DERIVED_FROM_128_EFUSE_BITS,
};
key_size = 16;
#else
@@ -112,7 +161,7 @@ static esp_err_t check_and_generate_encryption_keys(void)
esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = {
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,
};
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES64
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES128_DERIVED
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES256
#endif // CONFIG_IDF_TARGET_ESP32
@@ -163,8 +212,14 @@ static esp_err_t check_and_generate_encryption_keys(void)
return ESP_OK;
}
static esp_err_t initialise_flash_encryption(void)
esp_err_t esp_flash_encrypt_init(void)
{
if (esp_flash_encryption_enabled() || esp_flash_encrypt_initialized_once()) {
return ESP_OK;
}
/* Very first flash encryption pass: generate keys, etc. */
esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
/* Before first flash encryption pass, need to initialise key & crypto config */
@@ -190,26 +245,15 @@ static esp_err_t initialise_flash_encryption(void)
}
/* Encrypt all flash data that should be encrypted */
static esp_err_t encrypt_flash_contents(size_t flash_crypt_cnt, bool flash_crypt_wr_dis)
esp_err_t esp_flash_encrypt_contents(void)
{
esp_err_t err;
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
int num_partitions;
/* If all flash_crypt_cnt bits are burned or write-disabled, the
device can't re-encrypt itself. */
if (flash_crypt_wr_dis || flash_crypt_cnt == CRYPT_CNT[0]->bit_count) {
ESP_LOGE(TAG, "Cannot re-encrypt data CRYPT_CNT %d write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
return ESP_FAIL;
}
if (flash_crypt_cnt == 0) {
/* Very first flash of encrypted data: generate keys, etc. */
err = initialise_flash_encryption();
if (err != ESP_OK) {
return err;
}
}
#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1);
#endif
err = encrypt_bootloader();
if (err != ESP_OK) {
@@ -234,16 +278,38 @@ static esp_err_t encrypt_flash_contents(size_t flash_crypt_cnt, bool flash_crypt
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
return ESP_OK;
}
esp_err_t esp_flash_encrypt_enable(void)
{
esp_err_t err = ESP_OK;
if (!esp_flash_encryption_enabled()) {
if (esp_flash_encrypt_is_write_protected(true)) {
return ESP_FAIL;
}
size_t flash_crypt_cnt = get_flash_encrypt_cnt_value();
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
// Go straight to max, permanently enabled
ESP_LOGI(TAG, "Setting CRYPT_CNT for permanent encryption");
size_t new_flash_crypt_cnt = CRYPT_CNT[0]->bit_count - flash_crypt_cnt;
// Go straight to max, permanently enabled
ESP_LOGI(TAG, "Setting CRYPT_CNT for permanent encryption");
size_t new_flash_crypt_cnt = FLASH_ENC_CNT_MAX - flash_crypt_cnt;
#else
/* Set least significant 0-bit in flash_crypt_cnt */
size_t new_flash_crypt_cnt = 1;
/* Set least significant 0-bit in flash_crypt_cnt */
size_t new_flash_crypt_cnt = 1;
#endif
ESP_LOGD(TAG, "CRYPT_CNT %d -> %d", flash_crypt_cnt, new_flash_crypt_cnt);
err = esp_efuse_write_field_cnt(CRYPT_CNT, new_flash_crypt_cnt);
ESP_LOGD(TAG, "CRYPT_CNT %d -> %d", flash_crypt_cnt, new_flash_crypt_cnt);
err = esp_efuse_write_field_cnt(CRYPT_CNT, new_flash_crypt_cnt);
#if defined(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE) && defined(CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED)
// For AES128_DERIVED, FE key is 16 bytes and XTS_KEY_LENGTH_256 is 0.
// It is important to protect XTS_KEY_LENGTH_256 from further changing it to 1. Set write protection for this bit.
// Burning WR_DIS_CRYPT_CNT, blocks further changing of eFuses: DOWNLOAD_DIS_MANUAL_ENCRYPT, SPI_BOOT_CRYPT_CNT, [XTS_KEY_LENGTH_256], SECURE_BOOT_EN.
esp_efuse_write_field_bit(WR_DIS_CRYPT_CNT);
#endif
}
ESP_LOGI(TAG, "Flash encryption completed");
@@ -64,12 +64,14 @@ static esp_err_t secure_boot_v2_check(bool *need_fix)
{
esp_err_t err = ESP_OK;
esp_efuse_block_t block = EFUSE_BLK_SECURE_BOOT;
#ifndef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
if (esp_efuse_get_key_dis_read(block)) {
ESP_LOGE(TAG, "eFuse BLOCK%d should be readable", block);
abort();
// This code is not achievable because the bootloader will not boot an app in this state.
// But we keep it here just in case (any unexpected behavior).
}
#endif
if (esp_efuse_block_is_empty(block)) {
ESP_LOGE(TAG, "eFuse BLOCK%d should not be empty", block);
abort();
@@ -331,8 +331,10 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
assert(esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE));
#endif
#ifndef CONFIG_SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER
assert(esp_secure_boot_enabled());
ESP_LOGI(TAG, "Secure boot permanently enabled");
#endif
return ESP_OK;
}