ESP32(eco3) 启用 Secure Boot V2 与 Flash Encryption 的流程

本篇文档用来说明 ESP32(eco3) 芯片同时使能 Secure Boot V2 和 flash 加密的操作流程,其中,flash 加密使用发布模式(Release Mode),使用主机生成的密钥对数据进行加密。

文章目录

1. 测试环境

IDF 版本:v4.4-rc1
测试设备:ESP32-WROOM-32E
测试例程:examples/system/ota/simple_ota_example

1. 未使能前查询 efuse

$ espefuse.py --chip esp32 summary                                      
Connecting....
espefuse.py v3.2-dev
EFUSE_NAME (Block) Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
BLK3_PART_RESERVE (BLOCK0):                        BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
ADC_VREF (BLOCK0):                                 Voltage reference calibration                      = 1072 R/W (0b10100)

Config fuses:
XPD_SDIO_FORCE (BLOCK0):                           Ignore MTDI pin (GPIO12) for VDD_SDIO on reset     = False R/W (0b0)
XPD_SDIO_REG (BLOCK0):                             If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset    = False R/W (0b0)
XPD_SDIO_TIEH (BLOCK0):                            If XPD_SDIO_FORCE & XPD_SDIO_REG                   = 1.8V R/W (0b0)
CLK8M_FREQ (BLOCK0):                               8MHz clock freq override                           = 53 R/W (0x35)
SPI_PAD_CONFIG_CLK (BLOCK0):                       Override SD_CLK pad (GPIO6/SPICLK)                 = 0 R/W (0b00000)
SPI_PAD_CONFIG_Q (BLOCK0):                         Override SD_DATA_0 pad (GPIO7/SPIQ)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_D (BLOCK0):                         Override SD_DATA_1 pad (GPIO8/SPID)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_HD (BLOCK0):                        Override SD_DATA_2 pad (GPIO9/SPIHD)               = 0 R/W (0b00000)
SPI_PAD_CONFIG_CS0 (BLOCK0):                       Override SD_CMD pad (GPIO11/SPICS0)                = 0 R/W (0b00000)
DISABLE_SDIO_HOST (BLOCK0):                        Disable SDIO host                                  = False R/W (0b0)

Efuse fuses:
WR_DIS (BLOCK0):                                   Efuse write disable mask                           = 0 R/W (0x0000)
RD_DIS (BLOCK0):                                   Efuse read disable mask                            = 0 R/W (0x0)
CODING_SCHEME (BLOCK0):                            Efuse variable block length scheme                
   = NONE (BLK1-3 len=256 bits) R/W (0b00)
KEY_STATUS (BLOCK0):                               Usage of efuse block 3 (reserved)                  = False R/W (0b0)

Identity fuses:
MAC (BLOCK0):                                      Factory MAC Address                               
   = e8:9f:6d:d7:94:34 (CRC 0x19 OK) R/W 
MAC_CRC (BLOCK0):                                  CRC8 for factory MAC address                       = 25 R/W (0x19)
CHIP_VER_REV1 (BLOCK0):                            Silicon Revision 1                                 = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0):                            Silicon Revision 2                                 = True R/W (0b1)
CHIP_VERSION (BLOCK0):                             Reserved for future chip versions                  = 2 R/W (0b10)
CHIP_PACKAGE (BLOCK0):                             Chip package identifier                            = 1 R/W (0b001)
MAC_VERSION (BLOCK3):                              Version of the MAC field                           = 0 R/W (0x00)

Security fuses:
FLASH_CRYPT_CNT (BLOCK0):                          Flash encryption mode counter                      = 0 R/W (0b0000000)
UART_DOWNLOAD_DIS (BLOCK0):                        Disable UART download mode (ESP32 rev3 only)       = False R/W (0b0)
FLASH_CRYPT_CONFIG (BLOCK0):                       Flash encryption config (key tweak bits)           = 0 R/W (0x0)
CONSOLE_DEBUG_DISABLE (BLOCK0):                    Disable ROM BASIC interpreter fallback             = True R/W (0b1)
ABS_DONE_0 (BLOCK0):                               Secure boot V1 is enabled for bootloader image     = False R/W (0b0)
ABS_DONE_1 (BLOCK0):                               Secure boot V2 is enabled for bootloader image     = False R/W (0b0)
JTAG_DISABLE (BLOCK0):                             Disable JTAG                                       = False R/W (0b0)
DISABLE_DL_ENCRYPT (BLOCK0):                       Disable flash encryption in UART bootloader        = False R/W (0b0)
DISABLE_DL_DECRYPT (BLOCK0):                       Disable flash decryption in UART bootloader        = False R/W (0b0)
DISABLE_DL_CACHE (BLOCK0):                         Disable flash cache in UART bootloader             = False R/W (0b0)
BLOCK1 (BLOCK1):                                   Flash encryption key                              
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 
BLOCK2 (BLOCK2):                                   Secure boot key                                   
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 
BLOCK3 (BLOCK3):                                   Variable Block 3                                  
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 

Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).

2. 通过 menuconfig 配置使能

2.1 将 ESP32 芯片版本设置为 revision 3

配置路径:(Top) -> Component config -> ESP32-specific -> Minimum Supported ESP32 Revision (Rev 3)
ESP32(eco3) 启用 Secure Boot V2 与 Flash Encryption 的流程

2.2 调整分区表偏移量

使能 flash 加密以及 secure boot v2 后,生成的 bootloader bin 会变大,可以通过调整分区表地址增大 bootloader 分区大小,本例中将分区表偏移量从默认的 0x8000 调整到 0xF000,这样 bootloader 分区的大小为 0xF000 - 0x1000 = 0xE000(0x1000 为 bootloader bin 烧录地址),可以参考引导加载程序大小
配置路径:(Top) -> Partition Table -> (0xf000) Offset of partition table
ESP32(eco3) 启用 Secure Boot V2 与 Flash Encryption 的流程

2.3 安全特征配置

本例中,secure boot 版本为 v2,flash 加密模式为 Release 模式。
相关配置路径如下:
secure boot v2:
(Top) -> Security features -> [*] Enable hardware Secure Boot in bootloader (READ DOCS FIRST)
(Top) -> Security features -> [*] Enable hardware Secure Boot in bootloader (READ DOCS FIRST) -> Select secure boot version (Enable Secure Boot version 2)
(Top) -> Security features -> [*] Sign binaries during build
flash 加密:
(Top) -> Security features -> [*] Enable flash encryption on boot (READ DOCS FIRST)
(Top) -> Security features -> Enable flash encryption on boot (READ DOCS FIRST) -> Enable usage mode (Release)
(Top) -> Security features -> UART ROM download mode (UART ROM download mode (Enabled (not recommended)))
ESP32(eco3) 启用 Secure Boot V2 与 Flash Encryption 的流程
补充说明:

如果使能 Sign binaries during build, 将会在构建过程中对 app/partition bin 进行签名, Secure boot private signing key中指定的文件将用于对 app/partition bin 进行签名。
如果该选项禁用,将会生成未签名的 app/partition bin,必须使用 espsecure.py 手动签名。
可使用下面的命令手动签名:
espsecure.py sign_data --version 2 --keyfile ./my_signing_key.pem --output ./image_signed.bin image-unsigned.bin
可参考 Manual Commands

注意事项:

在量产过程中,建议将 UART ROM download mode 设置为 Permanently disabled(永久性禁用),以减少攻击者可用的选项。
参考官方文档说明:

如果用户已经预先生成了 flash 加密密钥并存储了一个副本,并且 UART 下载模式没有通过 CONFIG_SECURE_UART_ROM_DL_MODE (ESP32 V3 only) 永久禁用,那么可以通过使用 espsecure.py encrypt_flash_data 预加密文件,从而在在本地更新 flash,然后烧录密文。

本例中为了以防操作不当从而导致损坏芯片,故选择使能。

测试过程中禁用 NVS 加密,配置路径: (Top) -> Component config -> NVS -> [ ] Enable NVS encryption,具体说明见常见问题

3. 测试流程

3.1 secure boot v2 秘钥生成与烧录

可使用如下指令生成签名秘钥,参考 Generating Secure Boot Signing Key

espsecure.py generate_signing_key --version 2 secure_boot_signing_key.pem

生成 secure-bootloader-key.bin,该 bin 文件为公钥的 SHA-256 摘要,参考 eFuse usage

espsecure.py digest_rsa_public_key --keyfile secure_boot_signing_key.pem -o secure-bootloader-key.bin

烧录 secure-bootloader-key.bin:

espefuse.py burn_key secure_boot_v2 secure-bootloader-key.bin

烧录 ABS_DONE_1,该 efuse 用于在启动时使能 secure boot v2 保护。

espefuse.py burn_efuse ABS_DONE_1

3.2 flash 加密秘钥生成与烧录

生成 flash 加密秘钥,该秘钥可用于对于明文数据进行加密:

espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin

烧录 flash 加密秘钥:

python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_key flash_encryption my_flash_encryption_key.bin

flash 相关 efuse 烧录:

$ python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_efuse FLASH_CRYPT_CNT
$ python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_efuse FLASH_CRYPT_CONFIG 0xf

下面的 efuse 位说明可以参考启用 UART 引导加载程序加密/解密

$ python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_efuse DISABLE_DL_ENCRYPT
$ python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_efuse DISABLE_DL_DECRYPT
$ python $IDF_PATH/components/esptool_py/esptool/espefuse.py burn_efuse DISABLE_DL_CACHE

烧录完成后,查询 efuse 值如下:

$ espefuse.py --chip esp32 summary                                      
Connecting....
espefuse.py v3.2-dev
EFUSE_NAME (Block) Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
BLK3_PART_RESERVE (BLOCK0):                        BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
ADC_VREF (BLOCK0):                                 Voltage reference calibration                      = 1072 R/W (0b10100)

Config fuses:
XPD_SDIO_FORCE (BLOCK0):                           Ignore MTDI pin (GPIO12) for VDD_SDIO on reset     = False R/W (0b0)
XPD_SDIO_REG (BLOCK0):                             If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset    = False R/W (0b0)
XPD_SDIO_TIEH (BLOCK0):                            If XPD_SDIO_FORCE & XPD_SDIO_REG                   = 1.8V R/W (0b0)
CLK8M_FREQ (BLOCK0):                               8MHz clock freq override                           = 53 R/W (0x35)
SPI_PAD_CONFIG_CLK (BLOCK0):                       Override SD_CLK pad (GPIO6/SPICLK)                 = 0 R/W (0b00000)
SPI_PAD_CONFIG_Q (BLOCK0):                         Override SD_DATA_0 pad (GPIO7/SPIQ)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_D (BLOCK0):                         Override SD_DATA_1 pad (GPIO8/SPID)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_HD (BLOCK0):                        Override SD_DATA_2 pad (GPIO9/SPIHD)               = 0 R/W (0b00000)
SPI_PAD_CONFIG_CS0 (BLOCK0):                       Override SD_CMD pad (GPIO11/SPICS0)                = 0 R/W (0b00000)
DISABLE_SDIO_HOST (BLOCK0):                        Disable SDIO host                                  = False R/W (0b0)

Efuse fuses:
WR_DIS (BLOCK0):                                   Efuse write disable mask                           = 384 R/W (0x0180)
RD_DIS (BLOCK0):                                   Efuse read disable mask                            = 1 R/W (0x1)
CODING_SCHEME (BLOCK0):                            Efuse variable block length scheme                
   = NONE (BLK1-3 len=256 bits) R/W (0b00)
KEY_STATUS (BLOCK0):                               Usage of efuse block 3 (reserved)                  = False R/W (0b0)

Identity fuses:
MAC (BLOCK0):                                      Factory MAC Address                               
   = e8:9f:6d:d7:94:34 (CRC 0x19 OK) R/W 
MAC_CRC (BLOCK0):                                  CRC8 for factory MAC address                       = 25 R/W (0x19)
CHIP_VER_REV1 (BLOCK0):                            Silicon Revision 1                                 = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0):                            Silicon Revision 2                                 = True R/W (0b1)
CHIP_VERSION (BLOCK0):                             Reserved for future chip versions                  = 2 R/W (0b10)
CHIP_PACKAGE (BLOCK0):                             Chip package identifier                            = 1 R/W (0b001)
MAC_VERSION (BLOCK3):                              Version of the MAC field                           = 0 R/W (0x00)

Security fuses:
FLASH_CRYPT_CNT (BLOCK0):                          Flash encryption mode counter                      = 1 R/W (0b0000001)
UART_DOWNLOAD_DIS (BLOCK0):                        Disable UART download mode (ESP32 rev3 only)       = False R/W (0b0)
FLASH_CRYPT_CONFIG (BLOCK0):                       Flash encryption config (key tweak bits)           = 15 R/W (0xf)
CONSOLE_DEBUG_DISABLE (BLOCK0):                    Disable ROM BASIC interpreter fallback             = True R/W (0b1)
ABS_DONE_0 (BLOCK0):                               Secure boot V1 is enabled for bootloader image     = False R/W (0b0)
ABS_DONE_1 (BLOCK0):                               Secure boot V2 is enabled for bootloader image     = True R/W (0b1)
JTAG_DISABLE (BLOCK0):                             Disable JTAG                                       = False R/W (0b0)
DISABLE_DL_ENCRYPT (BLOCK0):                       Disable flash encryption in UART bootloader        = True R/W (0b1)
DISABLE_DL_DECRYPT (BLOCK0):                       Disable flash decryption in UART bootloader        = True R/W (0b1)
DISABLE_DL_CACHE (BLOCK0):                         Disable flash cache in UART bootloader             = True R/W (0b1)
BLOCK1 (BLOCK1):                                   Flash encryption key                              
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- 
BLOCK2 (BLOCK2):                                   Secure boot key                                   
   = ea b0 ba ca 3a 7f 44 99 03 e3 e8 7e 7c bc 17 a2 81 4c 3f 2b aa fd 23 00 ce 5f fc a3 8f df e2 1e R/- 
BLOCK3 (BLOCK3):                                   Variable Block 3                                  
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 

Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).

3.3 编译 bootloader

$ idf.py bootloader               

对应的输出日志如下,生成签名后的 build/bootloader/bootloader.bin

==============================================================================
Bootloader built. Secure boot enabled, so bootloader not flashed automatically.
Secure boot enabled, so bootloader not flashed automatically.
        /home/mali/.espressif/python_env/idf4.4_py3.8_env/bin/python  /home/mali/esp/master-idf/components/esptool_py/esptool/esptool.py --chip esp32 --port=(PORT) --baud=(BAUD) --before=default_reset --after=no_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader.bin
==============================================================================
[101/103] Generating binary image from built executable
esptool.py v3.2-dev
Merged 1 ELF section
Generated /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader.bin
[102/103] cd /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/esp-idf/esptool_py && /home/mali/.espressif/python_env/idf4.4_py3.8_env/bin/python /home/mali/esp/master-idf/components/partition_table/check_sizes.py --offset 0xf000 bootloader 0x1000 /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader.bin
Bootloader binary size 0xa230 bytes. 0x3dd0 bytes (28%) free.
[103/103] Generated the signed Bootloader
espsecure.py v3.2-dev
Padding data contents by 3536 bytes so signature sector aligns at sector boundary
1 signing key(s) found.
Signed 45056 bytes of data from /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader-unsigned.bin. Signature sector now has 1 signature blocks.
Generated signed binary image /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader.bin from /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/bootloader/bootloader-unsigned.bin
[9/9] Completed 'bootloader'

Bootloader build complete.

3.4 编译生成 app/partition bin 文件

$ idf.py build

对应的输出日志如下,生成 simple_ota.bin(已签名)、partition-table.binota_data_initial.bin

[1011/1013] Generating binary image from built executable
esptool.py v3.2-dev
Merged 25 ELF sections
Generated /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/simple_ota-unsigned.bin
[1012/1013] Generating signed binary image
espsecure.py v3.2-dev
1 signing key(s) found.
Signed 851968 bytes of data from /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/simple_ota-unsigned.bin. Signature sector now has 1 signature blocks.
Generated signed binary image /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/simple_ota.bin from /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/simple_ota-unsigned.bin
[1013/1013] cd /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/esp-idf/esptool_...tition-table.bin /home/mali/esp/master-idf/examples/system/ota/simple_ota_example/build/simple_ota.bin
simple_ota.bin binary size 0xd1000 bytes. Smallest app partition is 0x100000 bytes. 0x2f000 bytes (18%) free.

Project build complete. To flash, run this command:
/home/mali/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after no_reset --chip esp32  write_flash --flash_mode dio --flash_size keep --flash_freq 40m 0xf000 build/partition_table/partition-table.bin 0x14000 build/ota_data_initial.bin 0x20000 build/simple_ota.bin
or run 'idf.py -p (PORT) flash'

3.4 对 bin 文件进行加密

可以使用 idf.py partition-table 查询 app bin 文件的烧录地址:
本例中,输出如下:

Partition table binary generated. Contents:
*******************************************************************************
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x10000,16K,
otadata,data,ota,0x14000,8K,
phy_init,data,phy,0x16000,4K,
factory,app,factory,0x20000,1M,
ota_0,app,ota_0,0x120000,1M,
ota_1,app,ota_1,0x220000,1M,
*******************************************************************************

对 bootloader.bin 进行加密:

$ espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x1000 -o build/bootloader/bootloader_encryped.bin  build/bootloader/bootloader.bin

对 ota_data_initial.bin 进行加密:

$ espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x14000 -o build/ota_data_initial_encrypted.bin  build/ota_data_initial.bin

对 simple_ota.bin 进行加密:

$ espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0x20000 -o build/simple_ota_encrypted.bin  build/simple_ota.bin

对 partition-table.bin 进行加密:

$ espsecure.py encrypt_flash_data --keyfile my_flash_encryption_key.bin --address 0xf000 -o build/partition_table/partition-table-encrypted.bin   build/partition_table/partition-table.bin

3.5 烧录加密后的 bin 文件

$ esptool.py -b 921600 write_flash 0x1000 build/bootloader/bootloader_encryped.bin 0xf000 build/partition_table/partition-table-encrypted.bin 0x14000 build/ota_data_initial_encrypted.bin 0x20000 build/simple_ota_encrypted.bin

3.6 运行设备

--- idf_monitor on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
ets Jul 29 2019 12:21:46

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:2, clock div:2
secure boot v2 enabled
secure boot verification succeeded
load:0x3fff0038 len:0x3664
load:0x40078000 len:0x5c34
load:0x40080400 len:0xed0
0x40080400: _init at ??:?

entry 0x40080694
I (57) boot: ESP-IDF v4.4-rc1-dirty 2nd stage bootloader
I (57) boot: compile time 19:20:31
I (57) boot: chip revision: 3
I (60) boot.esp32: SPI Speed      : 40MHz
I (65) boot.esp32: SPI Mode       : DIO
I (69) boot.esp32: SPI Flash Size : 4MB
I (74) boot: Enabling RNG early entropy source...
I (79) boot: Partition Table:
I (83) boot: ## Label            Usage          Type ST Offset   Length
I (90) boot:  0 nvs              WiFi data        01 02 00010000 00004000
I (98) boot:  1 otadata          OTA data         01 00 00014000 00002000
I (105) boot:  2 phy_init         RF data          01 01 00016000 00001000
I (113) boot:  3 factory          factory app      00 00 00020000 00100000
I (120) boot:  4 ota_0            OTA app          00 10 00120000 00100000
I (128) boot:  5 ota_1            OTA app          00 11 00220000 00100000
I (135) boot: End of partition table
I (140) boot: Defaulting to factory image
I (144) esp_image: segment 0: paddr=00020020 vaddr=3f400020 size=1c128h (114984) map
I (196) esp_image: segment 1: paddr=0003c150 vaddr=3ffb0000 size=03780h ( 14208) load
I (202) esp_image: segment 2: paddr=0003f8d8 vaddr=40080000 size=00740h (  1856) load
I (203) esp_image: segment 3: paddr=00040020 vaddr=400d0020 size=8f050h (585808) map
I (429) esp_image: segment 4: paddr=000cf078 vaddr=40080740 size=13a48h ( 80456) load
I (464) esp_image: segment 5: paddr=000e2ac8 vaddr=50000000 size=00010h (    16) load
I (464) esp_image: segment 6: paddr=000e2ae0 vaddr=00000000 size=0d4f0h ( 54512) 
I (489) esp_image: Verifying image signature...
I (490) secure_boot_v2: Verifying with RSA-PSS...
I (494) secure_boot_v2: Signature verified successfully!
I (505) boot: Loaded app from partition at offset 0x20000
I (505) secure_boot_v2: enabling secure boot v2...
I (506) secure_boot_v2: secure boot v2 is already enabled, continuing..
I (514) boot: Checking flash encryption...
I (518) flash_encrypt: flash encryption is enabled (0 plaintext flashes left)
I (526) boot: Disabling RNG early entropy source...
I (543) cpu_start: Pro cpu up.
I (543) cpu_start: Starting app cpu, entry point is 0x40081148
0x40081148: call_start_cpu1 at /home/mali/esp/master-idf/components/esp_system/port/cpu_start.c:156

I (0) cpu_start: App cpu up.
I (560) cpu_start: Pro cpu start user code
I (560) cpu_start: cpu freq: 160000000
I (560) cpu_start: Application information:
I (564) cpu_start: Project name:     simple_ota
I (569) cpu_start: App version:      v4.4-rc1-dirty
I (575) cpu_start: Compile time:     Feb  1 2022 19:21:25
I (581) cpu_start: ELF file SHA256:  3558892d209a45c6...
I (587) cpu_start: ESP-IDF:          v4.4-rc1-dirty
I (593) heap_init: Initializing. RAM available for dynamic allocation:
I (600) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (606) heap_init: At 3FFB7538 len 00028AC8 (162 KiB): DRAM
I (612) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (618) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (625) heap_init: At 40094188 len 0000BE78 (47 KiB): IRAM
I (632) spi_flash: detected chip: generic
I (636) spi_flash: flash io: dio
I (640) flash_encrypt: Flash encryption mode is RELEASE
I (647) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (757) simple_ota_example: SHA-256 for bootloader:  e246cdf680a06d555681ad253fc7687812b3eca851fae5fdfd3746f01729b478
I (767) simple_ota_example: SHA-256 for current firmware:  d205254da1034217040298677071cc0662d03d7d8be89f44d45c08ee33c6a715
I (787) wifi:wifi driver task: 3ffc02a0, prio:23, stack:6656, core=0
I (787) system_api: Base MAC address is not set
I (787) system_api: read default base MAC address from EFUSE
I (817) wifi:wifi firmware version: 7679c42
I (817) wifi:wifi certification version: v7.0
I (817) wifi:config NVS flash: enabled
I (817) wifi:config nano formating: disabled
I (817) wifi:Init data frame dynamic rx buffer num: 32
I (827) wifi:Init management frame dynamic rx buffer num: 32
I (827) wifi:Init management short buffer num: 32
I (837) wifi:Init dynamic tx buffer num: 32
I (837) wifi:Init static rx buffer size: 1600
I (837) wifi:Init static rx buffer num: 10
I (847) wifi:Init dynamic rx buffer num: 32
I (847) wifi_init: rx ba win: 6
I (847) wifi_init: tcpip mbox: 32
I (857) wifi_init: udp mbox: 6
I (857) wifi_init: tcp mbox: 6
I (867) wifi_init: tcp tx win: 5744
I (867) wifi_init: tcp rx win: 5744
I (867) wifi_init: tcp mss: 1440
I (877) wifi_init: WiFi IRAM OP enabled
I (877) wifi_init: WiFi RX IRAM OP enabled

设备第一次启动后,查询设备 efuse 值:

$ espefuse.py --chip esp32 summary                                                                                                                                                    
Connecting....
espefuse.py v3.2-dev
EFUSE_NAME (Block) Description  = [Meaningful Value] [Readable/Writeable] (Hex Value)
----------------------------------------------------------------------------------------
Calibration fuses:
BLK3_PART_RESERVE (BLOCK0):                        BLOCK3 partially served for ADC calibration data   = False R/W (0b0)
ADC_VREF (BLOCK0):                                 Voltage reference calibration                      = 1072 R/W (0b10100)

Config fuses:
XPD_SDIO_FORCE (BLOCK0):                           Ignore MTDI pin (GPIO12) for VDD_SDIO on reset     = False R/W (0b0)
XPD_SDIO_REG (BLOCK0):                             If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset    = False R/W (0b0)
XPD_SDIO_TIEH (BLOCK0):                            If XPD_SDIO_FORCE & XPD_SDIO_REG                   = 1.8V R/W (0b0)
CLK8M_FREQ (BLOCK0):                               8MHz clock freq override                           = 53 R/W (0x35)
SPI_PAD_CONFIG_CLK (BLOCK0):                       Override SD_CLK pad (GPIO6/SPICLK)                 = 0 R/W (0b00000)
SPI_PAD_CONFIG_Q (BLOCK0):                         Override SD_DATA_0 pad (GPIO7/SPIQ)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_D (BLOCK0):                         Override SD_DATA_1 pad (GPIO8/SPID)                = 0 R/W (0b00000)
SPI_PAD_CONFIG_HD (BLOCK0):                        Override SD_DATA_2 pad (GPIO9/SPIHD)               = 0 R/W (0b00000)
SPI_PAD_CONFIG_CS0 (BLOCK0):                       Override SD_CMD pad (GPIO11/SPICS0)                = 0 R/W (0b00000)
DISABLE_SDIO_HOST (BLOCK0):                        Disable SDIO host                                  = False R/W (0b0)

Efuse fuses:
WR_DIS (BLOCK0):                                   Efuse write disable mask                           = 388 R/W (0x0184)
RD_DIS (BLOCK0):                                   Efuse read disable mask                            = 1 R/W (0x1)
CODING_SCHEME (BLOCK0):                            Efuse variable block length scheme                
   = NONE (BLK1-3 len=256 bits) R/W (0b00)
KEY_STATUS (BLOCK0):                               Usage of efuse block 3 (reserved)                  = False R/W (0b0)

Identity fuses:
MAC (BLOCK0):                                      Factory MAC Address                               
   = e8:9f:6d:d7:94:34 (CRC 0x19 OK) R/W 
MAC_CRC (BLOCK0):                                  CRC8 for factory MAC address                       = 25 R/W (0x19)
CHIP_VER_REV1 (BLOCK0):                            Silicon Revision 1                                 = True R/W (0b1)
CHIP_VER_REV2 (BLOCK0):                            Silicon Revision 2                                 = True R/W (0b1)
CHIP_VERSION (BLOCK0):                             Reserved for future chip versions                  = 2 R/W (0b10)
CHIP_PACKAGE (BLOCK0):                             Chip package identifier                            = 1 R/W (0b001)
MAC_VERSION (BLOCK3):                              Version of the MAC field                           = 0 R/W (0x00)

Security fuses:
FLASH_CRYPT_CNT (BLOCK0):                          Flash encryption mode counter                      = 1 R/- (0b0000001)
UART_DOWNLOAD_DIS (BLOCK0):                        Disable UART download mode (ESP32 rev3 only)       = False R/- (0b0)
FLASH_CRYPT_CONFIG (BLOCK0):                       Flash encryption config (key tweak bits)           = 15 R/W (0xf)
CONSOLE_DEBUG_DISABLE (BLOCK0):                    Disable ROM BASIC interpreter fallback             = True R/W (0b1)
ABS_DONE_0 (BLOCK0):                               Secure boot V1 is enabled for bootloader image     = False R/W (0b0)
ABS_DONE_1 (BLOCK0):                               Secure boot V2 is enabled for bootloader image     = True R/W (0b1)
JTAG_DISABLE (BLOCK0):                             Disable JTAG                                       = False R/W (0b0)
DISABLE_DL_ENCRYPT (BLOCK0):                       Disable flash encryption in UART bootloader        = True R/W (0b1)
DISABLE_DL_DECRYPT (BLOCK0):                       Disable flash decryption in UART bootloader        = True R/W (0b1)
DISABLE_DL_CACHE (BLOCK0):                         Disable flash cache in UART bootloader             = True R/W (0b1)
BLOCK1 (BLOCK1):                                   Flash encryption key                              
   = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? -/- 
BLOCK2 (BLOCK2):                                   Secure boot key                                   
   = ea b0 ba ca 3a 7f 44 99 03 e3 e8 7e 7c bc 17 a2 81 4c 3f 2b aa fd 23 00 ce 5f fc a3 8f df e2 1e R/- 
BLOCK3 (BLOCK3):                                   Variable Block 3                                  
   = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W 

Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).

发布模式会写保护 FLASH_CRYPT_CNT eFuse 位,可以看到:FLASH_CRYPT_CNT1 R/W (0b0000001) 变为 1 R/- (0b0000001)

常见问题

1.设备启动后会出现如下报错,是什么原因?

I (638) flash_encrypt: Flash encryption mode is RELEASE
I (645) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
E (655) nvs: CONFIG_NVS_ENCRYPTION is enabled, but no partition with subtype nvs_keys found in the partition table.
ESP_ERROR_CHECK failed: esp_err_t 0xffffffff (ESP_FAIL) at 0x40088204
0x40088204: _esp_error_check_failed at /home/mali/esp/master-idf/components/esp_system/esp_err.c:42

file: "../main/simple_ota_example.c" line 164
func: app_main
expression: err

abort() was called at PC 0x40088207 on core 0
0x40088207: _esp_error_check_failed at /home/mali/esp/master-idf/components/esp_system/esp_err.c:43

A:默认情况下,如果 flash 加密使能,NVS 加密会默认使能,配置路径如下:(Top) -> Component config -> NVS -> Enable NVS encryption,
如果使用 NVS 加密,分区表必须包含类型为 data,子类型为 nvs_keys 的 NVS 秘钥分区,参考 NVS 加密
本例使用的是示例默认的分区表(Factory app, two OTA definitions),不包含 NVS 秘钥分区,为了避免出现上述错误,在测试中禁用 NVS 加密。

参考链接

flash 加密
Secure Boot V2
ESP32-Secure Boot 安全方案

上一篇:解决报错:AddressSanitizer: heap-buffer-overflow


下一篇:00后是真干不过,公司新来的00后测试员已把我卷崩溃了...