产品:适用 ESP32 ECO0 ~ ECO2 版本的芯片

需求:

  • Secure Boot V1
  • Flash 加密 Release 模式,并使用随机密钥进行一机一密加密。
  • NVS 加密

可以先使用 Flash下载工具读 Flash 芯片版本信息:

在这里插入图片描述

1. 基于 esp-idf/examples/security/flash_encryption 例程测试

分区表设置如下:

# Name,   Type, SubType, Offset,  Size, Flags
nvs,           data, nvs,      , 0x6000,
# Extra partition to demonstrate reading/writing of encrypted flash
storage,       data, 0xff,     , 0x1000, encrypted
factory,       app,  factory,  , 1M,
# nvs_key partition contains the key that encrypts the NVS partition named nvs. The nvs_key partition needs to be encrypted.
nvs_key,       data, nvs_keys, , 0x1000, encrypted,
# Custom NVS data partition
custom_nvs,    data, nvs,      , 0x6000,
# FATFS partitions, one non-encrypted, one encrypted
fat_encrypted, data, fat,      , 600k,   encrypted
fat_not_encr,  data, fat,      , 600k,

2. 生成各项 Key

  • 生成 Secure Boot V1 签名 Key
espsecure.py generate_signing_key secure_boot_signing_key.pem --version 1 --scheme ecdsa256

在这里插入图片描述

  • 生成 Secure Boot 签名 Key 的公钥的摘要
espsecure.py digest_rsa_public_key --keyfile secure_boot_signing_key.pem --output public_key_digest.bin

在这里插入图片描述

  • 生成 NVS 加密 key
python E:\esp2\Espressif\frameworks\esp-idf-v5.4\esp-idf\components\nvs_flash\nvs_partition_generator\nvs_partition_gen.py generate-key --keyfile nvs_key.bin

在这里插入图片描述

在这里插入图片描述

3. 软件设置如下:

  • Flash Size 的设置
    Flash Size 的设置不大于硬件的 Flash Size 大小。不小于分区表设置的分区总和大小。

在这里插入图片描述

  • 分区表设置:

此工程使用工程下自定义的分区表文件:

在这里插入图片描述

在这里插入图片描述

  • 芯片版本设置:
    在这里插入图片描述

  • Flash 加密 Release 模式Secure Boot V1 以及禁用下载模式的设置

在这里插入图片描述

  • NVS 加密设置

在这里插入图片描述

4. 编译固件

idf.py build

查看编译日志,获取各分区下载地址:

在这里插入图片描述

*******************************************************************************
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0xe000,24K,
storage,data,255,0x14000,4K,encrypted
factory,app,factory,0x20000,1M,
nvs_key,data,nvs_keys,0x120000,4K,encrypted
custom_nvs,data,nvs,0x121000,24K,
fat_encrypted,data,fat,0x127000,600K,encrypted
fat_not_encr,data,fat,0x1bd000,600K,
*******************************************************************************

5. 获取待下载固件

查看工程编译日志,获取需下载的固件和对应的下载地址

0x1000 E:/esp2/Espressif/frameworks/esp-idf-v5.4/esp-idf/examples/security/flash_encryption/build/bootloader/bootloader.bin
0xd000 build\partition_table\partition-table.bin 
0x20000 build\flash_encryption.bin

在这里插入图片描述
在这里插入图片描述

由于开启了 NVS 加密,并使用唯一key 进行 NVS 分区的加密,故 nvs_key.bin 需随应用固件一起烧录

需要下载的固件和对应下载地址:

  • bootloader.bin : 0x1000
  • Signed partition-table.bin:0xd000
  • Signed flash_encryption.bin:0x20000
  • nvs_key.bin : 0x120000

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6. 收集所有 key 文件和所有待下载固件

在这里插入图片描述

7. Flash 下载工具的安全设置

flash_download_tool\configure\esp32 文件进行配置
在这里插入图片描述

[SECURE BOOT]
secure_boot_en = True
secure_boot_version = 1
public_key_digest_path = .\bin\all-file-bin-release-disable-download-securebootV1\public_key_digest.bin

[FLASH ENCRYPTION]
flash_encryption_en = True
reserved_burn_times = 0

[SECURE OTHER CONFIG]
flash_encryption_use_customer_key_enable = False
flash_encryption_use_customer_key_path = .\secure\flash_encrypt_key.bin
flash_force_write_enable = False

[FLASH ENCRYPTION KEYS LOCAL SAVE]
keys_save_enable = True
encrypt_keys_enable = False
encrypt_keys_aeskey_path = 

[ESP32 EFUSE BIT CONFIG]
jtag_disable = True
dl_encrypt_disable = True
dl_decrypt_disable = True
dl_cache_disable = True

在这里插入图片描述

在这里插入图片描述

Flash 下载工具将在固件烧录过程生成随机 Flash 加密 Key 用于固件的加密,再将加密后的固件写入 Flash


8. 导入待下载的固件和地址

在这里插入图片描述

固件下载日志:

test offset :  4096 0x1000
case ok
test offset :  53248 0xd000
case ok
test offset :  131072 0x20000
case ok
test offset :  1179648 0x120000
case ok
.
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 115200
Changed.
FLASH_CRYPT_CNT 0
ABS_DONE_0 False
CODING_SCHEME 0
ECDSA NIST256p private key in PEM format written to ./secure\secure_boot_key_1.pem
CODING_SCHEME 0
SHA-256 digest of private key ./secure\secure_boot_key_1.pem written to ./secure\secure_boot_key_1.bin
Using 256-bit key
digest+image written to E:\Download\flash_download_tool_20250217\flash_download_tool\dl_temp\bin_tmp\downloadPanel1\bootloader-digest-0x0000.bin
Encrypting bin file ...please wait!!!
Using 256-bit key
Encrypting bin file ...please wait!!!
Using 256-bit key
Note: Padding with 12 bytes of random data (encrypted data must be multiple of 16 bytes long)
Encrypting bin file ...please wait!!!
Using 256-bit key
Note: Padding with 12 bytes of random data (encrypted data must be multiple of 16 bytes long)
Encrypting bin file ...please wait!!!
Using 256-bit key
burn secure key ...
Burn keys to blocks:
 - BLOCK2 -> [77 18 89 e3 af d8 4e eb 43 54 b9 a8 44 55 48 82 b9 bb 82 ac 9f 70 d1 51 8c 2f 48 8b be 77 87 8c]
        Reversing the byte order
        Disabling read to key block
        Disabling write to key block

 - BLOCK1 -> [4a 28 c3 80 c5 23 20 87 b5 46 33 50 54 96 22 29 88 66 ae ec 06 b0 1a 6c 65 3c 11 d2 fa a0 1f 4e]
        Reversing the byte order
        Disabling read to key block
        Disabling write to key block

Burn keys in efuse blocks.
The key block will be read and write protected


Check all blocks for burn...
idx, BLOCK_NAME,          Conclusion
[00] BLOCK0               is not empty
        (written ): 0x0000000400000000000011330000a200001efcf5c44b532c00000000
        (to write): 0x00000000000000000000000000000000000000000000000000030180
        (coding scheme = NONE)
[01] BLOCK1               is empty, will burn the new value
[02] BLOCK2               is empty, will burn the new value
.
This is an irreversible operation!
BURN BLOCK2  - OK (write block == read block)
BURN BLOCK1  - OK (write block == read block)
BURN BLOCK0  - OK (all write block bits are set)
Reading updated efuses...
Successful
FLASH_CRYPT_CNT 0
FLASH_CRYPT_CONFIG 0
The efuses to burn:
  from BLOCK0
     - ABS_DONE_0
     - FLASH_CRYPT_CNT
     - FLASH_CRYPT_CONFIG

Burning efuses:

    - 'ABS_DONE_0' (Secure boot V1 is enabled for bootloader image) 0b0 -> 0b1

    - 'FLASH_CRYPT_CNT' (Flash encryption is enabled if this field has an odd number of bits set) 0b0000000 -> 0b1111111

    - 'FLASH_CRYPT_CONFIG' (Flash encryption config (key tweak bits)) 0x0 -> 0xf


Check all blocks for burn...
idx, BLOCK_NAME,          Conclusion
[00] BLOCK0               is not empty
        (written ): 0x0000000400000000000011330000a200001efcf5c44b532c00030180
        (to write): 0x00000010f00000000000000000000000000000000000000007f00000
        (coding scheme = NONE)
.
This is an irreversible operation!
BURN BLOCK0  - OK (all write block bits are set)
Reading updated efuses...
Checking efuses...
Successful

WARNING: - compress and encrypt options are mutually exclusive
Will flash uncompressed

 is stub and send flash finish
The efuses to burn:
  from BLOCK0
     - JTAG_DISABLE
     - DISABLE_DL_ENCRYPT
     - DISABLE_DL_DECRYPT
     - DISABLE_DL_CACHE

Burning efuses:

    - 'JTAG_DISABLE' (Disable JTAG) 0b0 -> 0b1

    - 'DISABLE_DL_ENCRYPT' (Disable flash encryption in UART bootloader) 0b0 -> 0b1

    - 'DISABLE_DL_DECRYPT' (Disable flash decryption in UART bootloader) 0b0 -> 0b1

    - 'DISABLE_DL_CACHE' (Disable flash cache in UART bootloader) 0b0 -> 0b1


Check all blocks for burn...
idx, BLOCK_NAME,          Conclusion
[00] BLOCK0               is not empty
        (written ): 0x00000014f0000000000011330000a200001efcf5c44b532c07f30180
        (to write): 0x000003c0000000000000000000000000000000000000000000000000
        (coding scheme = NONE)
.
This is an irreversible operation!
BURN BLOCK0  - OK (all write block bits are set)
Reading updated efuses...
Checking efuses...
Successful

8. 固件启动日志

ets Jun  8 2016 00:22:57

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:0x3fff00c0,len:12356
load:0x40078000,len:27864
load:0x40080400,len:4
load:0x40080404,len:3860
entry 0x4008063c
I (40) boot: ESP-IDF v5.4-dirty 2nd stage bootloader
I (40) boot: compile time Mar 11 2025 14:46:12
I (41) boot: Multicore bootloader
I (42) boot: chip revision: v1.0
I (45) boot.esp32: SPI Speed      : 40MHz
I (49) boot.esp32: SPI Mode       : DIO
I (52) boot.esp32: SPI Flash Size : 4MB
I (56) boot: Enabling RNG early entropy source...
I (60) boot: Partition Table:
I (63) boot: ## Label            Usage          Type ST Offset   Length
I (69) boot:  0 nvs              WiFi data        01 02 0000e000 00006000
I (76) boot:  1 storage          Unknown data     01 ff 00014000 00001000
I (82) boot:  2 factory          factory app      00 00 00020000 00100000
I (89) boot:  3 nvs_key          NVS keys         01 04 00120000 00001000
I (95) boot:  4 custom_nvs       WiFi data        01 02 00121000 00006000
I (102) boot:  5 fat_encrypted    Unknown data     01 81 00127000 00096000
I (108) boot:  6 fat_not_encr     Unknown data     01 81 001bd000 00096000
I (115) boot: End of partition table
I (118) esp_image: segment 0: paddr=00020020 vaddr=3f400020 size=0c890h ( 51344) map
I (144) esp_image: segment 1: paddr=0002c8b8 vaddr=3ff80000 size=0001ch (    28) load
I (145) esp_image: segment 2: paddr=0002c8dc vaddr=3ffb0000 size=024cch (  9420) load
I (152) esp_image: segment 3: paddr=0002edb0 vaddr=40080000 size=01268h (  4712) load
I (158) esp_image: segment 4: paddr=00030020 vaddr=400d0020 size=24dfch (151036) map
I (217) esp_image: segment 5: paddr=00054e24 vaddr=40081268 size=0c270h ( 49776) load
I (238) esp_image: segment 6: paddr=0006109c vaddr=00000000 size=0eee4h ( 61156) 
I (260) esp_image: Verifying image signature...
I (592) boot: Loaded app from partition at offset 0x20000
I (592) secure_boot_v1: bootloader secure boot is already enabled. No need to generate digest. continuing..
I (595) boot: Checking flash encryption...
I (599) flash_encrypt: flash encryption is enabled (0 plaintext flashes left)
I (606) boot: Checking secure boot...
I (609) secure_boot_v1: bootloader secure boot is already enabled, continuing..
I (616) boot: Disabling RNG early entropy source...
I (633) cpu_start: Multicore app
I (641) cpu_start: Pro cpu start user code
I (641) cpu_start: cpu freq: 160000000 Hz
I (641) app_init: Application information:
I (641) app_init: Project name:     flash_encryption
I (646) app_init: App version:      v5.4-dirty
I (650) app_init: Compile time:     Mar 11 2025 14:44:34
I (655) app_init: ELF file SHA256:  7f8988a61...
I (659) app_init: ESP-IDF:          v5.4-dirty
I (664) efuse_init: Min chip rev:     v0.0
I (667) efuse_init: Max chip rev:     v3.99 
I (671) efuse_init: Chip rev:         v1.0
I (676) heap_init: Initializing. RAM available for dynamic allocation:
I (682) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (687) heap_init: At 3FFB2F00 len 0002D100 (180 KiB): DRAM
I (692) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (697) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (703) heap_init: At 4008D4D8 len 00012B28 (74 KiB): IRAM
I (710) spi_flash: detected chip: generic
I (712) spi_flash: flash io: dio
I (715) flash_encrypt: Flash encryption mode is RELEASE
I (720) nvs_sec_provider: NVS Encryption - Registering Flash encryption-based scheme...
I (729) main_task: Started on CPU0
I (739) main_task: Calling app_main()

Example to check Flash Encryption status
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision v1.0, 4MB external flash
FLASH_CRYPT_CNT eFuse value is 127
Flash encryption feature is enabled in RELEASE mode
Erasing partition "storage" (0x1000 bytes)
Writing data with esp_partition_write:
I (789) example: 0x3ffb4190   00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
I (789) example: 0x3ffb41a0   10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f  |................|
Reading with esp_partition_read:
I (799) example: 0x3ffb4170   00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
I (809) example: 0x3ffb4180   10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f  |................|
Reading with esp_flash_read:
I (819) example: 0x3ffb4170   ab 30 c4 3e 02 e5 52 5a  b0 05 b9 f7 c0 9f 22 67  |.0.>..RZ......"g|
I (829) example: 0x3ffb4180   95 94 f9 fe 31 b0 62 a6  62 e4 c6 af 99 6e 73 c0  |....1.b.b....ns.|
I (839) example: Partitions fat_not_encr and fat_encrypted for FATFS example are present
I (849) example_fatfs: FAT partition "fat_not_encr" is not encrypted. Size is (0x96000 bytes) 
I (849) example_fatfs: Formatting FAT filesystem
W (999) vfs_fat_spiflash: f_mount failed (13)
I (999) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
I (1399) vfs_fat_spiflash: Mounting again
I (1499) example_fatfs: Mounting FAT filesystem
I (1499) example_fatfs: Opening file
I (1799) example_fatfs: Written to file: 'the quick brown fox jumped over the lazy dog'
I (1799) example_fatfs: Reading file
I (1799) example_fatfs: Read from file: 'the quick brown fox jumped over the lazy dog'
I (1809) example_fatfs: Unmounting FAT filesystem
I (1919) example_fatfs: Read partition using esp_flash_read until test string is found
I (2069) example_fatfs: 0x3ffb414c   74 68 65 20 71 75 69 63  6b 20 62 72 6f 77 6e 20  |the quick brown |
I (2069) example_fatfs: 0x3ffb415c   66 6f 78 20 6a 75 6d 70  65 64 20 6f 76 65 72 20  |fox jumped over |
I (2079) example_fatfs: 0x3ffb416c   74 68 65 20 6c 61 7a 79  20 64 6f 67              |the lazy dog|
I (2089) example_fatfs: Test string was found at offset (0x8000)
I (2099) example_fatfs: FAT partition "fat_encrypted" is encrypted. Size is (0x96000 bytes) 
I (2099) example_fatfs: Formatting FAT filesystem
W (2229) vfs_fat_spiflash: f_mount failed (13)
I (2229) vfs_fat_spiflash: Formatting FATFS partition, allocation unit size=4096
I (2659) vfs_fat_spiflash: Mounting again
I (2849) example_fatfs: Mounting FAT filesystem
I (2849) example_fatfs: Opening file
I (3149) example_fatfs: Written to file: 'the quick brown fox jumped over the lazy dog'
I (3149) example_fatfs: Reading file
I (3149) example_fatfs: Read from file: 'the quick brown fox jumped over the lazy dog'
I (3159) example_fatfs: Unmounting FAT filesystem
I (3349) example_fatfs: Read partition using esp_flash_read at expected offset (0x8000) 
I (3349) example_fatfs: 0x3ffb4144   27 3c 7c 15 e3 c3 90 0c  d9 66 c6 86 2a be 66 25  |'<|......f..*.f%|
I (3349) example_fatfs: 0x3ffb4154   1b a2 92 75 8b ca 45 b3  01 3d 80 53 7c 3a 82 6b  |...u..E..=.S|:.k|
I (3359) example_fatfs: 0x3ffb4164   7d 4d 8c 9f c3 ad 63 8f  75 2d 0f bb              |}M....c.u-..|
I (3369) example_fatfs: Data does not match test string
I (3509) nvs: NVS partition "nvs" is encrypted.
I (3549) example: NVS partition "custom_nvs" is encrypted.
I (3559) main_task: Returned from app_main()

固件下载完成后,所有被加密的分区完成固件加密。且芯片在第一次上电启动时,直接运行加密固件。通过查看固件运行日志,可以看到 Flash 加密 、Secure Boot V1 、NVS 加密都正常开启。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐