智能家居matter协议模块乐鑫科技wifi加密芯片flash/NVS加密方案,将启用 Flash 加密方案的明文固件烧录到设备端,并启动设备端后,设备端将自动启用Flash 加密方案。设备端自动启用 Flash 加密方案的基本工作流程是:
1)Bootloader 读取 eFuse 中 SPI BOOT_CRYPT_CNT 区域的值,若未启用Flash 加密方案则启用 Flash 加密方案。默认情况下,该区域的值为0,代表还未启用 FIash 加密。
(2)Bootloader 检测存储 Flash 加密方案密的eFuse 区域BLOCK KEY中是否已经存储密钥若未预先烧录密钥,则自动生成密并写入 BLOCK KEY,然后开启该区域的读/写保护,软件将无法读/写密钥。
(3)通过智能家居matter协议模块乐鑫科技wifi加密芯片Flash 加密方案来加密 Flash 中需要加密的数据,包括 Bootloader、app 和其他在分区表中标记 encrypted 的分区数据。
(4) Bootloader 将 eFuse 中的 SPI BOOT_CRYPT_CNT 区域的值设置为 1,表示已经启用了Flash 加密方案。
(5)若 Flash 加密的工作模式为开发模式,则 eFuse 中的 SPI_BOOT_CRYPT_CNT 和DIS DOWNLOAD MANUAL ENCRYPT 区域将不被写保护,从而允许关闭 Flash 加密方案,并重新烧录加密固件。
(6)若 Flash 加密的工作模式为量产模式,则智能家居matter协议模块乐鑫科技wifi加密芯片eFuse 中的 SPI_BOOT_CRYPT_CNT 和DIS_DOWNLOAD_MANUAL_ENCRYPT 区域将被写保护,从而永久使用 Flash 加密方案并禁止重新烧录固件。
(7)设备端在自动重启后会加载并运行加密后的 Bootloader 固件和app 固件。
注意:启用 Flash 加密方案后,eFuse 的一些标志位将默认被置位,从而关闭一些系统功能,如JTAG。继续保留这些系统功能可能会带来安全风险,在测试阶段,如果需要保留这些标志位,请参考 ESP-IDF 编程指南中与 Flash 加密相关的说明。
启用 Flash 加密方案后,设备端在加载运行加密的 Bootloader 固件和 app 固件时,智能家居matter协议模块乐鑫科技wifi加密芯片先自动通过硬件模块解密对应的数据,再将解密后的数据加载到设备端的 iRAM和 Cache 中运行。此外启用 Flash 加密方案后,一些 API在读/写 Flash 上加密分区的数据时将自动加/解密数据。自动解密数据的 API 主要包括 esp_partition_read()、esp_flash_read_encrypted()、bootloader_flash_read();自动加密数据的 API 主要包括 esp_partition_write()、esp_flash_write encrypted()、bootloader_flash_write()。
特别地,启用 Flash 加密方案后,在执行 OTA 升级时,设备端接收的是明文数据,在将接收到的明文数据写入 Flash 时,将调用上述的esp_partition_write()函数自动加密数据,以适应 Flash 加密方案的特性。
注意:设备量产后,通过 OTA 升级功能可以远程更新 app 固件,但无法更新 Bootloader 固件因此启用智能家居matter协议模块乐鑫科技wifi加密芯片Flash 加密方案后,请注意 Bootloader 的相关配置,如 Log 级别的配置。
NVS 加密方案简介
Flash 加密方案并不直接保护存储在 NVS分区的数据,存储在 NVS分区的数据需要 NVS加密方案来保护其机密性。我们可以通过 menuconfig - Component config - NVS -Enable NVS encryption 选项启用NVS 加密,或者在代码中调用 nvs_flash_secureinit()函数启用它。
NVS 加密方案的基本原理:在分区表中定义一块不少于4KB的子类型为nvs_key 的分区在启用NVS加密方案后,将使用nvs_key 分区的密加密NVS分区的数据。一种支持NVS加密的典型分区表如下所示:
1.# Name,Typer, SubType,Offset, Size,Flags
2.nvs,data,0x6000,,nvs,
3.phy_init,data,phy,,0x1000,
4.factory,app,factory,, 1M,
5.nvs_key,data,nvs_keys,,0x1000,encrypted,
NVS 加密方案与 Flash 加密方案有很多类似的地方,例如:
(1)NVS加密方案使用的加密算法是对称加密算法 AES-XTS。如前所述,对称加密算法要求其密钥是保密的,这样才能保证加密后的数据不被分析破解。NVS 加密方案的密钥不能是明文的,因此该方案经常与 Flash 加密方案结合使用,其中智能家居matter协议模块乐鑫科技wifi加密芯片Flash 加密方案负责保护 nvs_key的密钥机密性,NVS 加密方案使用 nvs_key 保护NVS 分区的数据机密性。
(2)存储NVS 加密方案密的方式有两种:一种是手动方式,即手动生成一个密钥,并将密钥新写入指定的分区,另一种是自动方式,即在首次启用 NVS 加密方案,且对应的 nvs_key分区内容为空时,设备内部先自动调用 nvs_flash_generate_keys()函数生成密钥,再将密钥写入 nvs_key分区,并使用该密钥完成NVS 加/解密。
采用手动方式存储 NVS 加密方案密钥的步骤如下:
首先,生成一个包含密钥的文件,命令如下:
$ espsecure.Py generate_flash_encryption_key_my_nvs_encryption key.bin
然后,编译并烧录分区表,命令如下:
$ idf.py -P (PORT) partition_table-flash
后,将密钥烧录到指定的分区,命令如下:
$ parttool.py -P (PORT) --partition-table-offset "nvs_key_partition offset"write_partition --partition-name="name of nvs_key partition"--input "nvs_keypartition"
(3)启用NVS 加密方案后,以nvs_get 或nvs_set 开头的API,在读/写NVS分区的数据时将自动完成数据的加/解密。
注意:启用 Flash 加密方案后,推荐启用NVS 加密方案(默认启用),这是因为智能家居matter协议模块乐鑫科技wifi加密芯片Wi-Fi驱动程序在默认的 NVS 分区中存储了一些重要数据(如SSID 和密码)。NVS 加密方案可在多个不同的 NVS 分区中使用不同的 nvs_key,在初始化对应的 NVS 分区时,只需要指定使用的nvs_key即可。
13.3.7 Flash 加密方案和 NVS 加密方案的示例
ESP-IDF的examples/security/flash encryption 提供了 Flash 加密方案和NVS加密方案的示例。通过运行该示例,可以观察 Flash 加密和 NVS 加密后的 Log 信息。
如前所述,若 Flash 加密的工作模式为开发模式,则可以重复烧录固件。我们尝试使用下面的三条命令将固件数据烧录到启用了 Flash 加密方案(开发模式)的设备上。
命令1:
$ idf.py -P PORT flash monitor
命令2:
$ idf.py -p PORr encrypted-flash monitor
命令3:
$ idf.py -p PORT encrypted-app-flash monitor
上述三条命令执行的情况和结果分别是:当使用命令 1进行烧录时,Flash 上终存储的是明文数据,从而出现无法加载的错误:使用命令 2 将仅烧录加密的 Bootloader 固件、app 固件和分区表,设备可以正常加载运行:使用命令 3 将仅烧录加密的 app 固件,若 Bootloader 是加密的,则设备可以正常加载运行。
上述三条命令内部实际调用了 esptool.py,它们分别对应的 esptool.py 命令参数为:
$ esptool.py --chip esp32c3 -p /dev/ttyusB0 -b 460800 --before=default_reset--after= no_reset_write_flash --flash mode dio --flash freq 40m --flash size 2ME0x1000 bootloader/bootloader 0x20000 flash encryption,bin 0xa000 partition tablelpartition-table.bin
$ esptool.py --chip esp32c3 -p /dev/ttyuSB0 -b 460800 --before=default_reset--after= no_reset_write_flash --flash mode dio --flash freg 40m --flash size 2M--encrypt 0x1000 bootloader/bootloader 0x20000 flash encryption.bin 0xa000partition table/ partition-table.bin
$ esptool.py --chip esp32c3 -p /dev/ttyUSB0 -b 460800 --before=default_reset--after= no_reset_write_flash --flash_mode dio --flash_freg 40m --flash_size 2MB--encrypt 0x20000 flash_encryption.bin
通过对比 esptool.py 对应的选项和参数,我们不难得出结论:使用 esptool.py 进行烧录时,添加选项 --encrypt 后,将在烧录时启用 Flash 自动加密的功能,将加密后的数据写入 Flash 中。
启用智能家居matter协议模块乐鑫科技wifi加密芯片Flash 加密方案后,常见的几种错误如下:
(1)启用 Flash 加密方案后,若烧录的是明文 Bootloader 数据,则在启动设备后,可能出现如下的 Log:
rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
invalid header: 0xb414f76b
invalid header: 0xb414f76b
invalid header: 0xb414f76b
invalid header:0xb414f76b
invalid header: 0xb414f76b
invalid header: 0xb414f76b
invalid header: 0xb414f76b
(2) 启用 Flash 加密方案后,若烧录的是明文分区表,则在启动设备后,可能出现如下 Log:
rst:0x3 (SW RESET),boot:0x13 (SPI FAST FLASH BOOT)
configsip: 0,SPIWP:Oxee
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:10464
ho 0 tail 12 room 4
load:0x40078000,len:19168
load:0x40080400,Ien:6664
entry 0x40080764
I(60) boot: ESP-IDF 4.0-dev-763-g2c55fae6c-dirty 2nd stage bootloader
I (60) boot: compile time 19:15:54
I (62) boot: Enabling RNG early entropy source...
I (67) boot:SPI Speed:40MHz
I(72) boot; SPI Mode: DIO
I (76) boot: SPI Flash Size : 4MB
E(80) flash_parts: partition 0 invalid magic number 0x94f6
E(86) boot: Failed to verify partition table
E(91) boot: load partition table error!
(3)启用智能家居matter协议模块乐鑫科技wifi加密芯片Flash 加密方案后,若烧录的是明文 app 固件,则在启动设备后,可能出现如下Log:
rst:0x3 (SW RESET),boot:0x13 (SPI FAST FLASH BOOT)
configsip: 0,SPIWP:Oxee
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:13616
load:0x40080400,len:6664
entry 0x40080764
I(56) boot: ESP-IDE v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader
I (56) boot: compile time 15:37:14
I (58) boot: Enabling RNG early entropy source...
I(64) boot: SPI Speed: 40MHz
I (68) boot: SPI Mode: DIO
I (72) boot: SPI Flash size: 4MB
I (76) boot: Partition Table:
I (79) boot: ## Label Usage Type ST OffsetLength
I (87) boot: 0 nvs Wi-Fi data 01 02 0000a000 00006000
I (94) boot: 1 phy_init RF data 01 01 00010000 00001000
I (102) boot: 2 factory factory app 00 00 00020000 00100000
I (109) boot: End of partition table
I(113) esp image: image at 0x20000 has invalid magic byte
W (120) esp image: image at 0x20000 has invalid SPI mode 108
W (126) esp image: image at 0x20000 has invalid SPI size 11
E(132) boot: Factory app partition is not bootable
E (138) boot: No bootable app partitions in the partition table