2021-05-09 22:56:51 -04:00
/*
2022-01-17 21:32:56 -05:00
* SPDX - FileCopyrightText : 2015 - 2022 Espressif Systems ( Shanghai ) CO LTD
2021-05-09 22:56:51 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
2020-12-01 08:34:53 -05:00
# include <strings.h>
# include "bootloader_flash_priv.h"
# include "bootloader_random.h"
# include "esp_image_format.h"
# include "esp_flash_encrypt.h"
# include "esp_flash_partitions.h"
# include "esp_secure_boot.h"
2020-12-21 01:48:49 -05:00
# include "esp_efuse.h"
# include "esp_efuse_table.h"
2021-06-16 19:21:36 -04:00
# include "esp_log.h"
2020-12-21 01:48:49 -05:00
# include "hal/wdt_hal.h"
2022-01-17 21:32:56 -05:00
# ifdef CONFIG_IDF_TARGET_ESP32C2
2021-11-06 05:21:57 -04:00
// IDF-3899
2022-01-17 21:32:56 -05:00
# warning "Not support flash encryption on esp32c2 yet."
2021-11-06 05:21:57 -04:00
# endif
2020-12-01 08:34:53 -05:00
2021-06-16 19:21:36 -04:00
# ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
# if CONFIG_IDF_TARGET_ESP32
# define CRYPT_CNT ESP_EFUSE_FLASH_CRYPT_CNT
# define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT
# else
# define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT
# define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
# endif
/* 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 )
* and if required encrypt the partitions in flash memory
*/
2020-12-01 08:34:53 -05:00
static const char * TAG = " flash_encrypt " ;
/* Static functions for stages of flash encryption */
static esp_err_t initialise_flash_encryption ( void ) ;
2021-06-16 19:21:36 -04:00
static esp_err_t encrypt_flash_contents ( size_t flash_crypt_cnt , bool flash_crypt_wr_dis ) __attribute__ ( ( unused ) ) ;
2020-12-01 08:34:53 -05:00
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 ) ;
esp_err_t esp_flash_encrypt_check_and_update ( void )
{
2021-06-16 19:21:36 -04:00
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 ) ;
2020-12-01 08:34:53 -05:00
2021-06-16 19:21:36 -04:00
ESP_LOGV ( TAG , " CRYPT_CNT %d, write protection %d " , flash_crypt_cnt , flash_crypt_wr_dis ) ;
2020-12-01 08:34:53 -05:00
2021-06-16 19:21:36 -04:00
if ( flash_crypt_cnt % 2 = = 1 ) {
2020-12-01 08:34:53 -05:00
/* Flash is already encrypted */
2021-06-16 19:21:36 -04:00
int left = ( CRYPT_CNT [ 0 ] - > bit_count - flash_crypt_cnt ) / 2 ;
2020-12-21 01:48:49 -05:00
if ( flash_crypt_wr_dis ) {
left = 0 ; /* can't update FLASH_CRYPT_CNT, no more flashes */
2020-12-01 08:34:53 -05:00
}
ESP_LOGI ( TAG , " flash encryption is enabled (%d plaintext flashes left) " , left ) ;
return ESP_OK ;
} else {
2020-12-21 01:48:49 -05:00
# ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
2020-12-01 08:34:53 -05:00
/* Flash is not encrypted, so encrypt it! */
2020-12-21 01:48:49 -05:00
return encrypt_flash_contents ( flash_crypt_cnt , flash_crypt_wr_dis ) ;
# 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
2020-12-01 08:34:53 -05:00
}
}
2020-12-21 01:48:49 -05:00
static esp_err_t check_and_generate_encryption_keys ( void )
2020-12-01 08:34:53 -05:00
{
2021-06-16 19:21:36 -04:00
size_t key_size = 32 ;
# ifdef CONFIG_IDF_TARGET_ESP32
enum { BLOCKS_NEEDED = 1 } ;
esp_efuse_purpose_t purposes [ BLOCKS_NEEDED ] = {
ESP_EFUSE_KEY_PURPOSE_FLASH_ENCRYPTION ,
} ;
esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme ( EFUSE_BLK_ENCRYPT_FLASH ) ;
if ( coding_scheme ! = EFUSE_CODING_SCHEME_NONE & & coding_scheme ! = EFUSE_CODING_SCHEME_3_4 ) {
ESP_LOGE ( TAG , " Unknown/unsupported CODING_SCHEME value 0x%x " , coding_scheme ) ;
return ESP_ERR_NOT_SUPPORTED ;
2020-12-21 01:48:49 -05:00
}
2021-06-16 19:21:36 -04:00
if ( coding_scheme = = EFUSE_CODING_SCHEME_3_4 ) {
key_size = 24 ;
}
# else
# ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
enum { BLOCKS_NEEDED = 2 } ;
esp_efuse_purpose_t purposes [ BLOCKS_NEEDED ] = {
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ,
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ,
} ;
if ( esp_efuse_find_purpose ( ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY , NULL ) ) {
ESP_LOGE ( TAG , " XTS_AES_128_KEY is already in use, XTS_AES_256_KEY_1/2 can not be used " ) ;
2020-12-21 01:48:49 -05:00
return ESP_ERR_INVALID_STATE ;
}
2021-06-16 19:21:36 -04:00
# else
enum { BLOCKS_NEEDED = 1 } ;
esp_efuse_purpose_t purposes [ BLOCKS_NEEDED ] = {
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ,
} ;
# endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES256
# endif // CONFIG_IDF_TARGET_ESP32
2021-10-27 08:21:01 -04:00
/* Initialize all efuse block entries to invalid (max) value */
esp_efuse_block_t blocks [ BLOCKS_NEEDED ] = { [ 0 . . . BLOCKS_NEEDED - 1 ] = EFUSE_BLK_KEY_MAX } ;
2021-06-16 19:21:36 -04:00
bool has_key = true ;
for ( unsigned i = 0 ; i < BLOCKS_NEEDED ; i + + ) {
bool tmp_has_key = esp_efuse_find_purpose ( purposes [ i ] , & blocks [ i ] ) ;
if ( tmp_has_key ) { // For ESP32: esp_efuse_find_purpose() always returns True, need to check whether the key block is used or not.
tmp_has_key & = ! esp_efuse_key_block_unused ( blocks [ i ] ) ;
}
if ( i = = 1 & & tmp_has_key ! = has_key ) {
ESP_LOGE ( TAG , " Invalid efuse key blocks: Both AES-256 key blocks must be set. " ) ;
return ESP_ERR_INVALID_STATE ;
}
has_key & = tmp_has_key ;
}
2020-12-21 01:48:49 -05:00
2021-06-16 19:21:36 -04:00
if ( ! has_key ) {
/* Generate key */
2020-12-21 01:48:49 -05:00
uint8_t keys [ BLOCKS_NEEDED ] [ 32 ] = { 0 } ;
2021-06-16 19:21:36 -04:00
ESP_LOGI ( TAG , " Generating new flash encryption key... " ) ;
for ( unsigned i = 0 ; i < BLOCKS_NEEDED ; + + i ) {
bootloader_fill_random ( keys [ i ] , key_size ) ;
2020-12-01 08:34:53 -05:00
}
2021-06-16 19:21:36 -04:00
ESP_LOGD ( TAG , " Key generation complete " ) ;
2020-12-01 08:34:53 -05:00
2020-12-21 01:48:49 -05:00
esp_err_t err = esp_efuse_write_keys ( purposes , keys , BLOCKS_NEEDED ) ;
if ( err ! = ESP_OK ) {
if ( err = = ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS ) {
ESP_LOGE ( TAG , " Not enough free efuse key blocks (need %d) to continue " , BLOCKS_NEEDED ) ;
} else {
ESP_LOGE ( TAG , " Failed to write efuse block with purpose (err=0x%x). Can't continue. " , err ) ;
2020-12-01 08:34:53 -05:00
}
2020-12-21 01:48:49 -05:00
return err ;
2020-12-01 08:34:53 -05:00
}
2020-12-21 01:48:49 -05:00
} else {
2021-06-16 19:21:36 -04:00
for ( unsigned i = 0 ; i < BLOCKS_NEEDED ; i + + ) {
if ( ! esp_efuse_get_key_dis_write ( blocks [ i ] )
| | ! esp_efuse_get_key_dis_read ( blocks [ i ] )
| | ! esp_efuse_get_keypurpose_dis_write ( blocks [ i ] ) ) { // For ESP32: no keypurpose, it returns always True.
ESP_LOGE ( TAG , " Invalid key state, check read&write protection for key and keypurpose(if exists) " ) ;
return ESP_ERR_INVALID_STATE ;
}
}
ESP_LOGI ( TAG , " Using pre-loaded flash encryption key in efuse " ) ;
2020-12-01 08:34:53 -05:00
}
2021-06-16 19:21:36 -04:00
return ESP_OK ;
2020-12-21 01:48:49 -05:00
}
2020-12-01 08:34:53 -05:00
2020-12-21 01:48:49 -05:00
static esp_err_t initialise_flash_encryption ( void )
{
esp_efuse_batch_write_begin ( ) ; /* Batch all efuse writes at the end of this function */
2021-06-16 19:21:36 -04:00
/* Before first flash encryption pass, need to initialise key & crypto config */
esp_err_t err = check_and_generate_encryption_keys ( ) ;
if ( err ! = ESP_OK ) {
2020-12-21 01:48:49 -05:00
esp_efuse_batch_write_cancel ( ) ;
2021-06-16 19:21:36 -04:00
return err ;
2020-12-21 01:48:49 -05:00
}
2021-06-16 19:21:36 -04:00
err = esp_flash_encryption_enable_secure_features ( ) ;
if ( err ! = ESP_OK ) {
esp_efuse_batch_write_cancel ( ) ;
return err ;
}
2020-12-21 01:48:49 -05:00
2021-06-16 19:21:36 -04:00
err = esp_efuse_batch_write_commit ( ) ;
2020-12-21 01:48:49 -05:00
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Error programming security eFuses (err=0x%x). " , err ) ;
2021-06-16 19:21:36 -04:00
return err ;
2020-12-21 01:48:49 -05:00
}
2021-06-16 19:21:36 -04:00
return ESP_OK ;
2020-12-01 08:34:53 -05:00
}
/* Encrypt all flash data that should be encrypted */
2021-06-16 19:21:36 -04:00
static esp_err_t encrypt_flash_contents ( size_t flash_crypt_cnt , bool flash_crypt_wr_dis )
2020-12-01 08:34:53 -05:00
{
esp_err_t err ;
esp_partition_info_t partition_table [ ESP_PARTITION_TABLE_MAX_ENTRIES ] ;
int num_partitions ;
2021-06-16 19:21:36 -04:00
/* If all flash_crypt_cnt bits are burned or write-disabled, the
2020-12-01 08:34:53 -05:00
device can ' t re - encrypt itself . */
2021-06-16 19:21:36 -04:00
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 ) ;
2020-12-01 08:34:53 -05:00
return ESP_FAIL ;
}
2021-06-16 19:21:36 -04:00
if ( flash_crypt_cnt = = 0 ) {
2020-12-01 08:34:53 -05:00
/* Very first flash of encrypted data: generate keys, etc. */
err = initialise_flash_encryption ( ) ;
if ( err ! = ESP_OK ) {
return err ;
}
}
err = encrypt_bootloader ( ) ;
if ( err ! = ESP_OK ) {
return err ;
}
err = encrypt_and_load_partition_table ( partition_table , & num_partitions ) ;
if ( err ! = ESP_OK ) {
return err ;
}
/* Now iterate the just-loaded partition table, looking for entries to encrypt
*/
/* Go through each partition and encrypt if necessary */
for ( int i = 0 ; i < num_partitions ; i + + ) {
err = encrypt_partition ( i , & partition_table [ i ] ) ;
if ( err ! = ESP_OK ) {
return err ;
}
}
ESP_LOGD ( TAG , " All flash regions checked for encryption pass " ) ;
2020-12-21 01:48:49 -05:00
# ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
2021-06-16 19:21:36 -04:00
// 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 ;
# else
/* Set least significant 0-bit in flash_crypt_cnt */
size_t new_flash_crypt_cnt = 1 ;
2020-12-21 01:48:49 -05:00
# endif
2021-06-16 19:21:36 -04:00
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 ) ;
2020-12-01 08:34:53 -05:00
ESP_LOGI ( TAG , " Flash encryption completed " ) ;
2021-06-16 19:21:36 -04:00
return err ;
2020-12-01 08:34:53 -05:00
}
static esp_err_t encrypt_bootloader ( void )
{
esp_err_t err ;
uint32_t image_length ;
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
if ( esp_image_verify_bootloader ( & image_length ) = = ESP_OK ) {
ESP_LOGD ( TAG , " bootloader is plaintext. Encrypting... " ) ;
2020-12-21 01:48:49 -05:00
# if CONFIG_SECURE_BOOT_V2_ENABLED
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
if ( ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET ) {
ESP_LOGE ( TAG , " Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x) " , ESP_PARTITION_TABLE_OFFSET ) ;
return ESP_ERR_INVALID_SIZE ;
}
# endif // CONFIG_SECURE_BOOT_V2_ENABLED
2020-12-01 08:34:53 -05:00
err = esp_flash_encrypt_region ( ESP_BOOTLOADER_OFFSET , image_length ) ;
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Failed to encrypt bootloader in place: 0x%x " , err ) ;
return err ;
}
2021-06-16 19:21:36 -04:00
# ifdef CONFIG_SECURE_BOOT_V1_ENABLED
/* If secure boot is enabled and bootloader was plaintext, also
* need to encrypt secure boot IV + digest .
*/
ESP_LOGD ( TAG , " Encrypting secure bootloader IV & digest... " ) ;
err = esp_flash_encrypt_region ( FLASH_OFFS_SECURE_BOOT_IV_DIGEST , FLASH_SECTOR_SIZE ) ;
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Failed to encrypt bootloader IV & digest in place: 0x%x " , err ) ;
return err ;
}
# endif
2020-12-21 01:48:49 -05:00
ESP_LOGI ( TAG , " bootloader encrypted successfully " ) ;
2021-06-16 19:21:36 -04:00
} else {
2020-12-01 08:34:53 -05:00
ESP_LOGW ( TAG , " no valid bootloader was found " ) ;
2020-12-21 01:48:49 -05:00
return ESP_ERR_NOT_FOUND ;
2020-12-01 08:34:53 -05:00
}
2021-06-16 19:21:36 -04:00
return ESP_OK ;
2020-12-01 08:34:53 -05:00
}
static esp_err_t encrypt_and_load_partition_table ( esp_partition_info_t * partition_table , int * num_partitions )
{
esp_err_t err ;
/* Check for plaintext partition table */
err = bootloader_flash_read ( ESP_PARTITION_TABLE_OFFSET , partition_table , ESP_PARTITION_TABLE_MAX_LEN , false ) ;
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Failed to read partition table data " ) ;
return err ;
}
if ( esp_partition_table_verify ( partition_table , false , num_partitions ) = = ESP_OK ) {
ESP_LOGD ( TAG , " partition table is plaintext. Encrypting... " ) ;
esp_err_t err = esp_flash_encrypt_region ( ESP_PARTITION_TABLE_OFFSET ,
2021-06-16 19:21:36 -04:00
FLASH_SECTOR_SIZE ) ;
2020-12-01 08:34:53 -05:00
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Failed to encrypt partition table in place. %x " , err ) ;
return err ;
}
} else {
ESP_LOGE ( TAG , " Failed to read partition table data - not plaintext? " ) ;
return ESP_ERR_INVALID_STATE ;
}
/* Valid partition table loaded */
2020-12-21 01:48:49 -05:00
ESP_LOGI ( TAG , " partition table encrypted and loaded successfully " ) ;
2020-12-01 08:34:53 -05:00
return ESP_OK ;
}
2020-12-21 01:48:49 -05:00
2020-12-01 08:34:53 -05:00
static esp_err_t encrypt_partition ( int index , const esp_partition_info_t * partition )
{
esp_err_t err ;
bool should_encrypt = ( partition - > flags & PART_FLAG_ENCRYPTED ) ;
if ( partition - > type = = PART_TYPE_APP ) {
/* check if the partition holds a valid unencrypted app */
esp_image_metadata_t data_ignored ;
err = esp_image_verify ( ESP_IMAGE_VERIFY ,
& partition - > pos ,
& data_ignored ) ;
should_encrypt = ( err = = ESP_OK ) ;
2021-06-16 19:21:36 -04:00
} else if ( ( partition - > type = = PART_TYPE_DATA & & partition - > subtype = = PART_SUBTYPE_DATA_OTA )
| | ( partition - > type = = PART_TYPE_DATA & & partition - > subtype = = PART_SUBTYPE_DATA_NVS_KEYS ) ) {
2020-12-01 08:34:53 -05:00
/* check if we have ota data partition and the partition should be encrypted unconditionally */
should_encrypt = true ;
}
if ( ! should_encrypt ) {
return ESP_OK ;
} else {
/* should_encrypt */
ESP_LOGI ( TAG , " Encrypting partition %d at offset 0x%x (length 0x%x)... " , index , partition - > pos . offset , partition - > pos . size ) ;
err = esp_flash_encrypt_region ( partition - > pos . offset , partition - > pos . size ) ;
ESP_LOGI ( TAG , " Done encrypting " ) ;
if ( err ! = ESP_OK ) {
ESP_LOGE ( TAG , " Failed to encrypt partition %d " , index ) ;
}
return err ;
}
}
2020-12-21 01:48:49 -05:00
2020-12-01 08:34:53 -05:00
esp_err_t esp_flash_encrypt_region ( uint32_t src_addr , size_t data_length )
{
esp_err_t err ;
uint32_t buf [ FLASH_SECTOR_SIZE / sizeof ( uint32_t ) ] ;
if ( src_addr % FLASH_SECTOR_SIZE ! = 0 ) {
ESP_LOGE ( TAG , " esp_flash_encrypt_region bad src_addr 0x%x " , src_addr ) ;
return ESP_FAIL ;
}
2020-12-21 01:48:49 -05:00
wdt_hal_context_t rtc_wdt_ctx = { . inst = WDT_RWDT , . rwdt_dev = & RTCCNTL } ;
2020-12-01 08:34:53 -05:00
for ( size_t i = 0 ; i < data_length ; i + = FLASH_SECTOR_SIZE ) {
2020-12-21 01:48:49 -05:00
wdt_hal_write_protect_disable ( & rtc_wdt_ctx ) ;
wdt_hal_feed ( & rtc_wdt_ctx ) ;
wdt_hal_write_protect_enable ( & rtc_wdt_ctx ) ;
2020-12-01 08:34:53 -05:00
uint32_t sec_start = i + src_addr ;
err = bootloader_flash_read ( sec_start , buf , FLASH_SECTOR_SIZE , false ) ;
if ( err ! = ESP_OK ) {
goto flash_failed ;
}
err = bootloader_flash_erase_sector ( sec_start / FLASH_SECTOR_SIZE ) ;
if ( err ! = ESP_OK ) {
goto flash_failed ;
}
err = bootloader_flash_write ( sec_start , buf , FLASH_SECTOR_SIZE , true ) ;
if ( err ! = ESP_OK ) {
goto flash_failed ;
}
}
return ESP_OK ;
flash_failed :
ESP_LOGE ( TAG , " flash operation failed: 0x%x " , err ) ;
return err ;
}
2021-06-16 19:21:36 -04:00
# endif // CONFIG_SECURE_FLASH_ENC_ENABLED