mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
spi_flash: remove duplicate definition of spi_flash_unlock
The other (static) definition is in flash_ops.c, all references are also in flash_ops.c.
This commit is contained in:
parent
2f557d1a59
commit
12c9d9a564
@ -515,6 +515,20 @@ menu "Security features"
|
||||
|
||||
Only set this option in testing environments.
|
||||
|
||||
config SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
bool "Require flash encryption to be already enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
default N
|
||||
help
|
||||
If not set (default), and flash encryption is not yet enabled in eFuses, the 2nd stage bootloader
|
||||
will enable flash encryption: generate the flash encryption key and program eFuses.
|
||||
If this option is set, and flash encryption is not yet enabled, the bootloader will error out and
|
||||
reboot.
|
||||
If flash encryption is enabled in eFuses, this option does not change the bootloader behavior.
|
||||
|
||||
Only use this option in testing environments, to avoid accidentally enabling flash encryption on
|
||||
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
endmenu # Security features
|
||||
|
||||
|
@ -37,7 +37,7 @@ 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(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis);
|
||||
static esp_err_t encrypt_flash_contents(uint32_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);
|
||||
@ -60,8 +60,14 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
#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);
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,10 +444,13 @@ void start_cpu0_default(void)
|
||||
#endif
|
||||
|
||||
bootloader_flash_update_id();
|
||||
#if !CONFIG_SPIRAM_BOOT_INIT // If psram is uninitialized, we need to improve some flash configuration.
|
||||
esp_image_header_t fhdr;
|
||||
const esp_partition_t *partition = esp_ota_get_running_partition();
|
||||
spi_flash_read(partition->address, &fhdr, sizeof(esp_image_header_t));
|
||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
||||
esp_image_header_t fhdr = {0};
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
||||
// If psram is uninitialized, we need to improve some flash configuration.
|
||||
bootloader_flash_clock_config(&fhdr);
|
||||
bootloader_flash_gpio_config(&fhdr);
|
||||
bootloader_flash_dummy_config(&fhdr);
|
||||
|
@ -646,10 +646,4 @@ esp_err_t spi_flash_read(size_t src, void *dstv, size_t size)
|
||||
return spi_flash_translate_rc(err);
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_unlock(void)
|
||||
{
|
||||
esp_err_t err = esp_flash_set_chip_write_protect(NULL, false);
|
||||
return spi_flash_translate_rc(err);
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
|
@ -198,7 +198,7 @@ static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock(void)
|
||||
}
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
#endif
|
||||
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
|
||||
esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
|
||||
{
|
||||
@ -419,7 +419,7 @@ out:
|
||||
|
||||
return spi_flash_translate_rc(rc);
|
||||
}
|
||||
#endif
|
||||
#endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
|
||||
esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
|
||||
{
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <esp_attr.h>
|
||||
#include <esp_flash_encrypt.h>
|
||||
|
||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
|
||||
static void test_encrypted_write(size_t offset, const uint8_t *data, size_t length);
|
||||
static void verify_erased_flash(size_t offset, size_t length);
|
||||
|
||||
@ -23,14 +25,10 @@ static void setup_tests(void)
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("test 16 byte encrypted writes", "[spi_flash]")
|
||||
TEST_CASE("test 16 byte encrypted writes", "[flash_encryption][test_env=UT_T1_FlashEncryption]")
|
||||
{
|
||||
setup_tests();
|
||||
|
||||
if (!esp_flash_encryption_enabled()) {
|
||||
TEST_IGNORE_MESSAGE("flash encryption disabled, skipping spi_flash_write_encrypted() tests");
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX(ESP_OK,
|
||||
spi_flash_erase_sector(start / SPI_FLASH_SEC_SIZE));
|
||||
|
||||
@ -101,3 +99,4 @@ static void verify_erased_flash(size_t offset, size_t length)
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
|
@ -21,6 +21,24 @@ static uint32_t end;
|
||||
|
||||
static spi_flash_mmap_handle_t handle1, handle2, handle3;
|
||||
|
||||
static esp_err_t spi_flash_read_maybe_encrypted(size_t src_addr, void *des_addr, size_t size)
|
||||
{
|
||||
if (!esp_flash_encryption_enabled()) {
|
||||
return spi_flash_read(src_addr, des_addr, size);
|
||||
} else {
|
||||
return spi_flash_read_encrypted(src_addr, des_addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t spi_flash_write_maybe_encrypted(size_t des_addr, const void *src_addr, size_t size)
|
||||
{
|
||||
if (!esp_flash_encryption_enabled()) {
|
||||
return spi_flash_write(des_addr, src_addr, size);
|
||||
} else {
|
||||
return spi_flash_write_encrypted(des_addr, src_addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_mmap_tests(void)
|
||||
{
|
||||
if (start == 0) {
|
||||
@ -54,7 +72,7 @@ static void setup_mmap_tests(void)
|
||||
uint32_t sector_offs = abs_sector * SPI_FLASH_SEC_SIZE;
|
||||
bool sector_needs_write = false;
|
||||
|
||||
ESP_ERROR_CHECK( spi_flash_read(sector_offs, buffer, sizeof(buffer)) );
|
||||
ESP_ERROR_CHECK( spi_flash_read_maybe_encrypted(sector_offs, buffer, sizeof(buffer)) );
|
||||
|
||||
for (uint32_t word = 0; word < 1024; ++word) {
|
||||
uint32_t val = rand();
|
||||
@ -69,13 +87,13 @@ static void setup_mmap_tests(void)
|
||||
/* Only rewrite the sector if it has changed */
|
||||
if (sector_needs_write) {
|
||||
ESP_ERROR_CHECK( spi_flash_erase_sector((uint16_t) abs_sector) );
|
||||
ESP_ERROR_CHECK( spi_flash_write(sector_offs, (const uint8_t *) buffer, sizeof(buffer)) );
|
||||
ESP_ERROR_CHECK( spi_flash_write_maybe_encrypted(sector_offs, (const uint8_t *) buffer, sizeof(buffer)) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Can mmap into data address space", "[spi_flash]")
|
||||
TEST_CASE("Can mmap into data address space", "[spi_flash][mmap]")
|
||||
{
|
||||
setup_mmap_tests();
|
||||
|
||||
@ -135,7 +153,7 @@ TEST_CASE("Can mmap into data address space", "[spi_flash]")
|
||||
TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(start, SPI_FLASH_MMAP_DATA));
|
||||
}
|
||||
|
||||
TEST_CASE("Can mmap into instruction address space", "[mmap]")
|
||||
TEST_CASE("Can mmap into instruction address space", "[spi_flash][mmap]")
|
||||
{
|
||||
setup_mmap_tests();
|
||||
|
||||
@ -183,7 +201,7 @@ TEST_CASE("Can mmap into instruction address space", "[mmap]")
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Can mmap unordered pages into contiguous memory", "[spi_flash]")
|
||||
TEST_CASE("Can mmap unordered pages into contiguous memory", "[spi_flash][mmap]")
|
||||
{
|
||||
int nopages;
|
||||
int *pages;
|
||||
@ -226,7 +244,7 @@ TEST_CASE("Can mmap unordered pages into contiguous memory", "[spi_flash]")
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash]")
|
||||
TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash][mmap]")
|
||||
{
|
||||
const void *ptr1;
|
||||
|
||||
@ -275,7 +293,7 @@ TEST_CASE("flash_mmap invalidates just-written data", "[spi_flash]")
|
||||
handle1 = 0;
|
||||
}
|
||||
|
||||
TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash]")
|
||||
TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash][mmap]")
|
||||
{
|
||||
//this test case should make flash size >= 4MB, because max size of Dcache can mapped is 4MB
|
||||
setup_mmap_tests();
|
||||
@ -324,7 +342,7 @@ TEST_CASE("flash_mmap can mmap after get enough free MMU pages", "[spi_flash]")
|
||||
TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(start, SPI_FLASH_MMAP_DATA));
|
||||
}
|
||||
|
||||
TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash]")
|
||||
TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash][mmap]")
|
||||
{
|
||||
uint8_t buf[64];
|
||||
|
||||
@ -337,7 +355,7 @@ TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash]")
|
||||
TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_DATA));
|
||||
|
||||
/* Read the flash @ 'phys' and compare it to the data we get via regular cache access */
|
||||
spi_flash_read(phys, buf, sizeof(buf));
|
||||
spi_flash_read_maybe_encrypted(phys, buf, sizeof(buf));
|
||||
TEST_ASSERT_EQUAL_HEX32_ARRAY((void *)esp_partition_find, buf, sizeof(buf)/sizeof(uint32_t));
|
||||
|
||||
/* spi_flash_mmap is in IRAM */
|
||||
@ -353,11 +371,11 @@ TEST_CASE("phys2cache/cache2phys basic checks", "[spi_flash]")
|
||||
TEST_ASSERT_EQUAL_PTR(NULL, spi_flash_phys2cache(phys, SPI_FLASH_MMAP_INST));
|
||||
|
||||
/* Read the flash @ 'phys' and compare it to the data we get via normal cache access */
|
||||
spi_flash_read(phys, buf, sizeof(constant_data));
|
||||
spi_flash_read_maybe_encrypted(phys, buf, sizeof(constant_data));
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(constant_data, buf, sizeof(constant_data));
|
||||
}
|
||||
|
||||
TEST_CASE("mmap consistent with phys2cache/cache2phys", "[spi_flash]")
|
||||
TEST_CASE("mmap consistent with phys2cache/cache2phys", "[spi_flash][mmap]")
|
||||
{
|
||||
const void *ptr = NULL;
|
||||
const size_t test_size = 2 * SPI_FLASH_MMU_PAGE_SIZE;
|
||||
@ -382,7 +400,7 @@ TEST_CASE("mmap consistent with phys2cache/cache2phys", "[spi_flash]")
|
||||
TEST_ASSERT_EQUAL_HEX(SPI_FLASH_CACHE2PHYS_FAIL, spi_flash_cache2phys(ptr));
|
||||
}
|
||||
|
||||
TEST_CASE("munmap followed by mmap flushes cache", "[spi_flash]")
|
||||
TEST_CASE("munmap followed by mmap flushes cache", "[spi_flash][mmap]")
|
||||
{
|
||||
setup_mmap_tests();
|
||||
|
||||
@ -401,9 +419,10 @@ TEST_CASE("munmap followed by mmap flushes cache", "[spi_flash]")
|
||||
TEST_ASSERT_NOT_EQUAL(0, memcmp(buf, data, sizeof(buf)));
|
||||
}
|
||||
|
||||
TEST_CASE("no stale data read post mmap and write partition", "[spi_flash]")
|
||||
TEST_CASE("no stale data read post mmap and write partition", "[spi_flash][mmap]")
|
||||
{
|
||||
const char buf[] = "Test buffer data for partition";
|
||||
/* Buffer size is set to 32 to allow encrypted flash writes */
|
||||
const char buf[32] = "Test buffer data for partition";
|
||||
char read_data[sizeof(buf)];
|
||||
setup_mmap_tests();
|
||||
|
||||
@ -415,7 +434,9 @@ TEST_CASE("no stale data read post mmap and write partition", "[spi_flash]")
|
||||
SPI_FLASH_MMAP_DATA, (const void **) &data, &handle) );
|
||||
memcpy(read_data, data, sizeof(read_data));
|
||||
TEST_ESP_OK(esp_partition_erase_range(p, 0, SPI_FLASH_MMU_PAGE_SIZE));
|
||||
TEST_ESP_OK(esp_partition_write(p, 0, buf, sizeof(buf)));
|
||||
/* not using esp_partition_write here, since the partition in not marked as "encrypted"
|
||||
in the partition table */
|
||||
TEST_ESP_OK(spi_flash_write_maybe_encrypted(p->address + 0, buf, sizeof(buf)));
|
||||
/* This should retrigger actual flash content read */
|
||||
memcpy(read_data, data, sizeof(read_data));
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
# Flash Encryption
|
||||
|
||||
The example checks if the flash encryption feature is enabled/disabled and if enabled prints the flash encryption mode (DEVELOPMENT / RELEASE) and FLASH_CRYPT_CNT eFuse value
|
||||
The example checks if the flash encryption feature is enabled/disabled and if enabled prints the flash encryption mode (DEVELOPMENT / RELEASE) and FLASH_CRYPT_CNT eFuse value.
|
||||
|
||||
The example also demonstrates writing and reading encrypted partitions in flash.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
@ -21,7 +24,7 @@ idf.py menuconfig
|
||||
|
||||
### Build and Flash
|
||||
|
||||
When building the project and flashing it to the board FOR THE FIRST TIME after enabling flash encryption feature in menuconfig, run following command to program ESP32 and monitor the output
|
||||
When building the project and flashing it to the board FOR THE FIRST TIME after enabling flash encryption feature in menuconfig, run following command to program ESP32 and monitor the output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
@ -31,21 +34,40 @@ idf.py -p PORT flash monitor
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
When reprogramming the device subsequently use following command for encrypted write of new plaintext application
|
||||
When reprogramming the device subsequently use following command for encrypted write of new plaintext application:
|
||||
|
||||
```
|
||||
idf.py encrypted-app-flash monitor
|
||||
idf.py -p PORT encrypted-app-flash monitor
|
||||
```
|
||||
|
||||
Please note above command programs only the app partition. In order to reprogram all partitions (bootloader, partition table and application) in encrypted form use
|
||||
Please note above command programs only the app partition. In order to reprogram all partitions (bootloader, partition table and application) in encrypted form use:
|
||||
|
||||
```
|
||||
idf.py encrypted-flash monitor
|
||||
idf.py -p PORT encrypted-flash monitor
|
||||
```
|
||||
|
||||
## Example Output
|
||||
|
||||
When the device boots for the first time after enabling flash encryption in Development mode the output would contain following
|
||||
When running the example without enabling flash encryption, the output would be as follows:
|
||||
|
||||
```
|
||||
Example to check Flash Encryption status
|
||||
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 2MB external flash
|
||||
FLASH_CRYPT_CNT eFuse value is 0
|
||||
Flash encryption feature is disabled
|
||||
Erasing partition "storage" (0x1000 bytes)
|
||||
Writing data with esp_partition_write:
|
||||
I (378) example: 0x3ffb4dc0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
I (378) example: 0x3ffb4dd0 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
Reading with esp_partition_read:
|
||||
I (388) example: 0x3ffb4da0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
I (398) example: 0x3ffb4db0 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
Reading with spi_flash_read:
|
||||
I (408) example: 0x3ffb4da0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
I (418) example: 0x3ffb4db0 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
```
|
||||
|
||||
After enabling flash encryption in Development mode, the output shows the process of enabling the flash encryption:
|
||||
|
||||
```
|
||||
I (168) boot: Checking flash encryption...
|
||||
@ -64,74 +86,23 @@ I (13229) flash_encrypt: Flash encryption completed
|
||||
I (13229) boot: Resetting with flash encryption enabled...
|
||||
```
|
||||
|
||||
Once the flash encryption is enabled the device will reset itself. At this stage the flash contents are in encrypted form. The output would be similar to
|
||||
Once the flash encryption is enabled the device will reset itself. At this stage the flash contents are in encrypted form. The output would be similar to:
|
||||
|
||||
```
|
||||
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
|
||||
configsip: 0, SPIWP:0xee
|
||||
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
|
||||
mode:DIO, clock div:2
|
||||
load:0x3fff0018,len:4
|
||||
load:0x3fff001c,len:8452
|
||||
load:0x40078000,len:13652
|
||||
ho 0 tail 12 room 4
|
||||
load:0x40080400,len:6664
|
||||
entry 0x40080764
|
||||
I (30) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader
|
||||
I (30) boot: compile time 16:32:53
|
||||
I (31) boot: Enabling RNG early entropy source...
|
||||
I (37) boot: SPI Speed : 40MHz
|
||||
I (41) boot: SPI Mode : DIO
|
||||
I (45) boot: SPI Flash Size : 4MB
|
||||
I (49) boot: Partition Table:
|
||||
I (52) boot: ## Label Usage Type ST Offset Length
|
||||
I (60) boot: 0 nvs WiFi data 01 02 0000a000 00006000
|
||||
I (67) boot: 1 phy_init RF data 01 01 00010000 00001000
|
||||
I (75) boot: 2 factory factory app 00 00 00020000 00100000
|
||||
I (82) boot: End of partition table
|
||||
I (86) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map
|
||||
I (107) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) load
|
||||
I (111) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) load
|
||||
0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778
|
||||
|
||||
I (116) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) load
|
||||
I (134) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map
|
||||
0x400d0018: _flash_cache_start at ??:?
|
||||
|
||||
I (162) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) load
|
||||
0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561
|
||||
|
||||
I (171) boot: Loaded app from partition at offset 0x20000
|
||||
I (171) boot: Checking flash encryption...
|
||||
I (171) flash_encrypt: flash encryption is enabled (3 plaintext flashes left)
|
||||
I (178) boot: Disabling RNG early entropy source...
|
||||
I (184) cpu_start: Pro cpu up.
|
||||
I (188) cpu_start: Application information:
|
||||
I (193) cpu_start: Project name: flash-encryption
|
||||
I (198) cpu_start: App version: v4.0-dev-850-gc4447462d-dirty
|
||||
I (205) cpu_start: Compile time: Jun 17 2019 16:32:52
|
||||
I (211) cpu_start: ELF file SHA256: 8770c886bdf561a7...
|
||||
I (217) cpu_start: ESP-IDF: v4.0-dev-850-gc4447462d-dirty
|
||||
I (224) cpu_start: Starting app cpu, entry point is 0x40080e4c
|
||||
0x40080e4c: call_start_cpu1 at esp-idf/esp-idf/components/esp32/cpu_start.c:265
|
||||
|
||||
I (0) cpu_start: App cpu up.
|
||||
I (235) heap_init: Initializing. RAM available for dynamic allocation:
|
||||
I (241) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
|
||||
I (247) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM
|
||||
I (254) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
|
||||
I (260) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
|
||||
I (266) heap_init: At 40087FF4 len 0001800C (96 KiB): IRAM
|
||||
I (273) cpu_start: Pro cpu start user code
|
||||
I (291) cpu_start: Starting scheduler on PRO CPU.
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
|
||||
Sample program to check Flash Encryption
|
||||
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash
|
||||
Flash encryption feature is enabled
|
||||
Flash encryption mode is DEVELOPMENT
|
||||
Flash in encrypted mode with flash_crypt_cnt = 1
|
||||
Halting...
|
||||
Example to check Flash Encryption status
|
||||
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 4MB external flash
|
||||
FLASH_CRYPT_CNT eFuse value is 1
|
||||
Flash encryption feature is enabled in DEVELOPMENT mode
|
||||
Erasing partition "storage" (0x1000 bytes)
|
||||
Writing data with esp_partition_write:
|
||||
I (451) example: 0x3ffb4dc0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
I (451) example: 0x3ffb4dd0 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
Reading with esp_partition_read:
|
||||
I (461) example: 0x3ffb4da0 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
|
||||
I (471) example: 0x3ffb4db0 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
|
||||
Reading with spi_flash_read:
|
||||
I (491) example: 0x3ffb4da0 29 68 2e 13 88 a0 5b 7f cc 6b 39 f9 d7 7b 32 2f |)h....[..k9..{2/|
|
||||
I (491) example: 0x3ffb4db0 9f e6 55 37 4b 91 b0 83 cd a6 e9 4e cd fa b4 c7 |..U7K......N....|
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@ -139,7 +110,7 @@ I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
It is also possible to use esptool.py utility to read the eFuse values and check if flash encryption is enabled or not
|
||||
|
||||
```
|
||||
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/cu.SLAB_USBtoUART summary
|
||||
python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port PORT summary
|
||||
```
|
||||
|
||||
If FLASH_CRYPT_CNT eFuse value is non-zero flash encryption is enabled
|
||||
|
41
examples/security/flash_encryption/example_test.py
Normal file
41
examples/security/flash_encryption/example_test.py
Normal file
@ -0,0 +1,41 @@
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import IDF
|
||||
except ImportError:
|
||||
test_fw_path = os.getenv('TEST_FW_PATH')
|
||||
if test_fw_path and test_fw_path not in sys.path:
|
||||
sys.path.insert(0, test_fw_path)
|
||||
import IDF
|
||||
|
||||
|
||||
# To prepare a test runner for this example:
|
||||
# 1. Generate zero flash encryption key:
|
||||
# dd if=/dev/zero of=key.bin bs=1 count=32
|
||||
# 2.Burn Efuses:
|
||||
# espefuse.py --do-not-confirm -p $ESPPORT burn_efuse FLASH_CRYPT_CONFIG 0xf
|
||||
# espefuse.py --do-not-confirm -p $ESPPORT burn_efuse FLASH_CRYPT_CNT 0x1
|
||||
# espefuse.py --do-not-confirm -p $ESPPORT burn_key flash_encryption key.bin
|
||||
@IDF.idf_example_test(env_tag='Example_Flash_Encryption')
|
||||
def test_examples_security_flash_encryption(env, extra_data):
|
||||
dut = env.get_dut('flash_encryption', 'examples/security/flash_encryption')
|
||||
# start test
|
||||
dut.start_app()
|
||||
lines = [
|
||||
'FLASH_CRYPT_CNT eFuse value is 1',
|
||||
'Flash encryption feature is enabled in DEVELOPMENT mode',
|
||||
'with esp_partition_write',
|
||||
'00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f',
|
||||
'with esp_partition_read',
|
||||
'00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f',
|
||||
'with spi_flash_read',
|
||||
'29 68 2e 13 88 a0 5b 7f cc 6b 39 f9 d7 7b 32 2f'
|
||||
]
|
||||
for line in lines:
|
||||
dut.expect(line, timeout=2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_examples_security_flash_encryption()
|
@ -13,16 +13,29 @@
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
static void example_print_chip_info(void);
|
||||
static void example_print_flash_encryption_status(void);
|
||||
static void example_read_write_flash(void);
|
||||
|
||||
static const char* TAG = "example";
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt = 0;
|
||||
esp_flash_enc_mode_t mode;
|
||||
printf("\nExample to check Flash Encryption status\n");
|
||||
|
||||
printf("\nSample program to check Flash Encryption\n");
|
||||
example_print_chip_info();
|
||||
example_print_flash_encryption_status();
|
||||
example_read_write_flash();
|
||||
}
|
||||
|
||||
|
||||
static void example_print_chip_info(void)
|
||||
{
|
||||
/* Print chip information */
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
@ -35,33 +48,52 @@ void app_main(void)
|
||||
|
||||
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||
}
|
||||
|
||||
|
||||
static void example_print_flash_encryption_status(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_FLASH_CRYPT_CNT, &flash_crypt_cnt, 7);
|
||||
printf("FLASH_CRYPT_CNT eFuse value is %d\n", flash_crypt_cnt);
|
||||
|
||||
if (esp_flash_encryption_enabled()) {
|
||||
printf("Flash encryption feature is enabled\n");
|
||||
mode = esp_get_flash_encryption_mode();
|
||||
|
||||
if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
|
||||
printf("Flash encryption mode is DEVELOPMENT\n");
|
||||
/* If odd bits set flash encryption is enabled else disabled */
|
||||
if (__builtin_parity(flash_crypt_cnt) == 1) {
|
||||
printf("Flash in encrypted mode with flash_crypt_cnt = %d\n", flash_crypt_cnt);
|
||||
}
|
||||
else {
|
||||
printf("Flash in plaintext mode with flash_crypt_cnt = %d\n", flash_crypt_cnt);
|
||||
}
|
||||
} else {
|
||||
printf("Flash encryption mode is RELEASE\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("FLASH_CRYPT_CNT eFuse value is %d\n", flash_crypt_cnt);
|
||||
printf("Flash encryption feature is disabled\n\n");
|
||||
}
|
||||
|
||||
printf("Halting...\n");
|
||||
while(1) {
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
esp_flash_enc_mode_t mode = esp_get_flash_encryption_mode();
|
||||
if (mode == ESP_FLASH_ENC_MODE_DISABLED) {
|
||||
printf("Flash encryption feature is disabled\n");
|
||||
} else {
|
||||
printf("Flash encryption feature is enabled in %s mode\n",
|
||||
mode == ESP_FLASH_ENC_MODE_DEVELOPMENT ? "DEVELOPMENT" : "RELEASE");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void example_read_write_flash(void)
|
||||
{
|
||||
const esp_partition_t* partition = esp_partition_find_first(
|
||||
ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
|
||||
assert(partition);
|
||||
|
||||
printf("Erasing partition \"%s\" (0x%x bytes)\n", partition->label, partition->size);
|
||||
|
||||
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
|
||||
|
||||
/* Generate the data which will be written */
|
||||
const size_t data_size = 32;
|
||||
uint8_t plaintext_data[data_size];
|
||||
for (uint8_t i = 0; i < data_size; ++i) {
|
||||
plaintext_data[i] = i;
|
||||
}
|
||||
|
||||
printf("Writing data with esp_partition_write:\n");
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, plaintext_data, data_size, ESP_LOG_INFO);
|
||||
ESP_ERROR_CHECK(esp_partition_write(partition, 0, plaintext_data, data_size));
|
||||
|
||||
uint8_t read_data[data_size];
|
||||
printf("Reading with esp_partition_read:\n");
|
||||
ESP_ERROR_CHECK(esp_partition_read(partition, 0, read_data, data_size));
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, read_data, data_size, ESP_LOG_INFO);
|
||||
|
||||
printf("Reading with spi_flash_read:\n");
|
||||
ESP_ERROR_CHECK(spi_flash_read(partition->address, read_data, data_size));
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, read_data, data_size, ESP_LOG_INFO);
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
# Extra partition to demonstrate reading/writing of encrypted flash
|
||||
storage, data, 0xff, 0xf000, 0x1000, encrypted
|
||||
factory, app, factory, 0x10000, 1M,
|
|
12
examples/security/flash_encryption/sdkconfig.ci
Normal file
12
examples/security/flash_encryption/sdkconfig.ci
Normal file
@ -0,0 +1,12 @@
|
||||
# Default settings for testing this example in CI.
|
||||
# This configuration is not secure, don't use it in production!
|
||||
# See Flash Encryption API Guide for more details.
|
||||
|
||||
CONFIG_SECURE_FLASH_ENC_ENABLED=y
|
||||
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
|
||||
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
|
4
examples/security/flash_encryption/sdkconfig.defaults
Normal file
4
examples/security/flash_encryption/sdkconfig.defaults
Normal file
@ -0,0 +1,4 @@
|
||||
# This example uses an extra partition to demonstrate encrypted/non-encrypted reads/writes.
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
|
@ -196,6 +196,12 @@ example_test_007:
|
||||
- ESP32
|
||||
- Example_I2C_CCS811_SENSOR
|
||||
|
||||
example_test_008:
|
||||
extends: .example_test_template
|
||||
tags:
|
||||
- ESP32
|
||||
- Example_Flash_Encryption
|
||||
|
||||
UT_001:
|
||||
extends: .unit_test_template
|
||||
parallel: 50
|
||||
@ -412,6 +418,12 @@ UT_030:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
|
||||
UT_031:
|
||||
extends: .unit_test_template
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_FlashEncryption
|
||||
|
||||
nvs_compatible_test:
|
||||
extends: .test_template
|
||||
artifacts:
|
||||
|
@ -135,6 +135,11 @@ class IDFApp(App.BaseApp):
|
||||
# offs, filename
|
||||
flash_files.append((args[idx], args[idx + 1]))
|
||||
|
||||
# The build metadata file does not currently have details, which files should be encrypted and which not.
|
||||
# Assume that all files should be encrypted if flash encryption is enabled in development mode.
|
||||
sdkconfig_dict = self.get_sdkconfig()
|
||||
flash_settings["encrypt"] = "CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT" in sdkconfig_dict
|
||||
|
||||
# make file offsets into integers, make paths absolute
|
||||
flash_files = [(int(offs, 0), os.path.join(self.binary_path, path.strip())) for (offs, path) in flash_files]
|
||||
|
||||
|
@ -217,7 +217,7 @@ class IDFDUT(DUT.SerialDUT):
|
||||
'no_stub': False,
|
||||
'compress': True,
|
||||
'verify': False,
|
||||
'encrypt': False,
|
||||
'encrypt': self.app.flash_settings.get("encrypt", False),
|
||||
'erase_all': False,
|
||||
})
|
||||
|
||||
|
10
tools/unit-test-app/configs/flash_encryption
Normal file
10
tools/unit-test-app/configs/flash_encryption
Normal file
@ -0,0 +1,10 @@
|
||||
TEST_COMPONENTS=spi_flash
|
||||
TEST_GROUPS=flash_encryption
|
||||
CONFIG_SECURE_FLASH_ENC_ENABLED=y
|
||||
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC=y
|
||||
CONFIG_SECURE_BOOT_ALLOW_JTAG=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC=y
|
||||
CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE=y
|
||||
CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED=y
|
@ -78,6 +78,11 @@ spi_flash_write:
|
||||
module abbr: DRV
|
||||
sub module: SPI
|
||||
sub module abbr: SPI
|
||||
flash_encryption:
|
||||
module: Driver
|
||||
module abbr: DRV
|
||||
sub module: SPI
|
||||
sub module abbr: SPI
|
||||
esp32:
|
||||
module: System
|
||||
module abbr: SYS
|
||||
|
Loading…
Reference in New Issue
Block a user