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

View File

@@ -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");