Esp32 Flash Encryption Guide Cn
User Manual:
Open the PDF directly: View PDF
.
Page Count: 20

!
!
版本 1.0
版权 © 2017
ESP32 Flash 加密指南

录
1. 概述 1 .........................................................................................................................................
2. Flash 加密机制 2 ........................................................................................................................
3. Flash 加密初始化 3 ....................................................................................................................
4. 使 Flash 加密 4 .......................................................................................................................
4.1. Flash 解密的范围!4"........................................................................................................................
4.2. 读加密 Flash!4"...............................................................................................................................
4.3. 写加密 Flash!4"...............................................................................................................................
5. 新加密 Flash 6 ........................................................................................................................
5.1. OTA 升级!6"....................................................................................................................................
5.2. 烧写!6".....................................................................................................................................
5.3. 新 Flash 的限制!6".......................................................................................................................
5.4. 烧写的注意事项!6"...................................................................................................................
5.5. 重新烧写程序!6".......................................................................................................................
5.6. 关闭烧写!7"..............................................................................................................................
6. 预成 Flash 加密密钥 8 ............................................................................................................
6.1. 预成 Flash 加密密钥!8"................................................................................................................
6.2. 烧写 Flash 加密密钥!8"...................................................................................................................
6.3. 使预成的密钥进第次烧写!9".............................................................................................
6.4. 使预成的密钥重烧 Flash!9"......................................................................................................
7. 关闭 Flash 加密 10 .....................................................................................................................
8. Flash 加密的局限 11 ..................................................................................................................
9. Flash 加密级功能 12 ..............................................................................................................
9.1. 加密分区标志!12"............................................................................................................................
9.2. 启 UART 引导加载程序加解密!12"..............................................................................................
9.3. 设置 FLASH_CRYPT_CONFIG!13".................................................................................................

10.技术参考 14 ...............................................................................................................................
10.1. FLASH_CRYPT_CNT eFuse!14".....................................................................................................
10.2. FLASH 加密算法!14.......................................................................................................................

!
1. 概述"
1. 概述
ESP32 flash 加密功能于加密 ESP32 SPI flash 的内容。启 flash 加密时,部分
flash 内容可以防物读取。
Flash 加密功能与安全启动 (secure boot) 功能是分开的,户可以直接使 flash 加密功
能。但是,如果要保证安全的使环境,建议将这两个功能起使。
📖 说明:
启 flash 加密会限制后续对 flash 内容的新。使 flash 加密功能前请必阅读本档。
Espressif
!/!1 16
2017.07

!
2. Flash 加密机制"
2. Flash 加密机制
•Flash 的内容是使 256-bit 密钥的 AES 进加密的。Flash 加密密钥存储在芯内部
的 eFuse 中,并且(在默认情况下)软件能对其读写。
•通过 ESP32 的 flash 缓存映射功能可以对 flash 进透明读写,映射到地址空间的任意
flash 区域在读取时都会被透明解密。
•户将明数据烧录到 ESP32 来启动加密功能,引导加载程序会在次启动时对数据
在 flash 原处进加密。
•并所有的 flash 数据都会被加密。被加密 flash 数据包括:
-引导加载程序
- secure boot 引导加载程序摘要(如果启 secure boot)
-分区表
-所有“app”类型的分区
- OTA data 分区(OTA data 最多可以有个,当需要使 OTA 功能时会有该分区)
-分区表中所有标有“encrypt”的分区
些数据分区可能需要保持加密以于访问,或者可以使在数据加密时效的
flash 新算法。于失性存储的 NVS 分区能加密。
•Flash 加密密钥存储在 ESP32 芯内部的 eFuse 密钥块 1 中。默认情况下,该密钥是
读写保护的,软件法访问或改。
•Flash 加密的算法是 AES-256,密钥会根据 flash 的每 32 字节块的偏移地址进加密。
即 flash 的每 32 字节块(两个连续的 16 字节 AES 块)使个唯的密钥进加密,
这个唯的密钥是由 flash 加密密钥成的。
•虽然在芯上运的软件可以透明解密 flash 内容,但默认情况下,如果启动 flash
加密,则 UART 引导加载程序法解密(或加密)数据。
•所以,如果要使 flash 加密的功能,在编写代码时必须谨慎。
Espressif
!/!2 16
2017.07

!
3. Flash 加密初始化"
3. Flash 加密初始化
本章介绍默认(推荐)的 flash 加密初始化的过程。这个过程可以为开发或其他的定
制。详细信息请参阅章节 Flash 加密级功能。
启 flash 加密的过程如下:
1. 编译引导加载程序时必须确保持 flash 加密功能。在 make menuconfig 中,导航到
Security Features,将 Enable flash encryption on boot 勾选为 Yes。
2. 如果要使 Secure Boot 功能,则最好同时勾选这些选项。请先阅读 Secure Boot 的
档。
3. 构建并烧录引导程序、分区表和出 app image。这些分区最初被写 flash 时未加
密。
4. 第次启动时,引导加载程序会读出 FLASH_CRYPT_CNT eFuse 的值为 0(出默认
值),然后会使硬件随机数成成 flash 加密密钥。此密钥存储在 eFuse 中。此
密钥被读写保护,防软件进步访问。
5. 所有加密分区由引导加载程序直接就地加密。就地加密可能需要些时间(的分区可
能需要分钟)。
6. 烧写完成后,默认烧写 eFuse 来防加密的 flash在 UART 引导加载程序运时被访
问。
7. FLASH_CRYPT_CONFIG eFuse 也烧写为最值 (0xF),以最化 flash 算法中被修改的密
钥的特数。多信息请参阅章节设置 FLASH_CRYPT_CONFIG。
8. 最后,FLASH_CRYPT_CNT eFuse 被烧写为初始值 1。正是这个 eFuse 激活透明 flash
加密层,并限制后续重烧 flash 的次数。有关 FLASH_CRYPT_CNT eFuse 的详细信
息,请参阅章节升级加密 Flash。
9. 引导加载程序从新加密的 flash 中动重启。
⚠ 注意:
旦在第次启动时使 flash 加密功能,则硬件最多允许后续 3 次通过新 flash 内容。升级需
要遵循特定的程序,具体请参考章节烧写。
⚠ 注意:
第次启动加密正在运时要中断 ESP32 的电源。如果电源中断,flash 内容会被破坏,需要再次使未
加密的数据进烧写。重新烧写会计烧写的限制总数。
Espressif
!/!3 16
2017.07

!
4. 使 Flash 加密"
4. 使 Flash 加密
ESP32 app 代码可以通过调 esp_flash_encryption_enabled 检查 flash 加密是否启。
启 flash 加密后,从代码访问 flash 内容时需要注意以下事项。
4.1. Flash 解密的范围
每当 FLASH_CRYPT_CNT eFuse 的奇数个特被置为 1 时,通过 MMU的 flash 缓存访问的所
有 flash 内容都将被透明地解密。这些 flash 内容包括:
- flash (IROM) 中的可执 app 代码
-存储在 flash (DROM) 中的所有只读数据。
-通过 esp_spi_flash_mmap 访问的数据
-由 ROM 引导加载程序读取的软件 bootloader image。
4.2. 读加密 Flash
要读取数据使 flash 缓存 MMU 映射,我们建议使分区读取函数
esp_partition_read。使此函数时,只有加密分区中的数据才会被解密。其他分区将被
加密读取。这样,软件可以以相同的式访问加密和加密的 flash。
通过其他 SPI API 读取的数据会被解密:
-通过 esp_spi_flash_read 读取的数据被解密
-通过 ROM 函数 SPIRead() 读取的数据被解密(ESP-IDF app 持此函数)
-使失性存储 (NVS) API 存储的数据被加密,只能通过 SPI 的式读取明
数据。
4.3. 写加密 Flash
可能的话,建议使分区写函数 esp_partition_write。使此函数时,数据只有写加
密分区时才会被加密。数据写其他分区会被加密。这样,软件可以以相同的式访问
加密和加密的 flash。
⚠ 注意:
MMU flash 缓存条件地解密所有数据。在 flash 中未加密存储的数据会被“透明解密”,并且在软件看来是乱
码。
Espressif
!/!4 16
2017.07

!
4. 使 Flash 加密"
当 write_encrypted 参数设置为 true 时,esp_spi_flash_write 函数才会加密数据,否
则,会加密数据。
ROM 函数 esp_rom_spiflash_write_encrypted 把加密数据写 flash,ROM 函数
SPIWrite 把加密的数据写 flash。(ESP-IDF app 持这些函数)。
未加密数据的最写为 4 字节(对式为 4 字节)。由于数据以块的形式加密,
所以加密数据的最写为 16 字节(对式为 16 字节)。
Espressif
!/!5 16
2017.07

!
5. 新加密 Flash"
5. 新加密 Flash
5.1. OTA 升级
加密分区的 OTA 升级将动加密,使 esp_partition_write 函数即可。
5.2. 烧写
如果使 secure boot,FLASH_CRYPT_CNT eFuse 允许通过(或其他物法)重烧
flash,最多可以重烧 3次。
该过程涉及烧写明数据,然后重复烧写 FLASH_CRYPT_CNTeFuse,导致引导加载程序重
新加密此数据。
5.3. 新 Flash 的限制
加上初始的加密 flash,总共可以通过进 4 次烧写。
关闭第四次加密后,FLASH_CRYPT_CNT 的最值为 0xFF,加密被永久关闭。
使 OTA 升级或预成的加密密钥可以受次数的限制。
5.4. 烧写的注意事项
•当通过重新烧写时,要重新烧写每个最初写明数据的分区(包括引导加载程
序)。可以跳过是“当前选择的”OTA app 分区(除在那找到明 app image,否
则这些分区会被重新加密。)但是,任何标有“encrypt”标志的分区将条件地被重新
加密,这意味着任何已加密的数据将被次加密并被破坏。
使 makeflash 起烧写所有需要烧写的分区。
•如果启 secure boot,则法通过重新烧写,除启 secure boot的
Reflashable 选项,预成个密钥并将其烧写到 ESP32(请参阅 secure boot
档)。在这种情况下,您可以重新烧写明 secure boot 摘要和 bootloader image 到偏
移地址 0x0。在烧写其他明数据之前,需要重新烧写该摘要。
5.5. 重新烧写程序
1. 正常构建 app。
Espressif
!/!6 16
2017.07

!
5. 新加密 Flash"
2. 正常使明数据烧写设备(使 makeflash 或 esptool.py 命令。)烧写所有之前
加密的分区,包括引导程序(上节)。
3. 此时,设备将法启动(消息为 flashreaderr,1000),因为它需要个加密的引
导加载程序,但引导加载程序是明。
4. 通过运命令 espefuse.pyburn_efuseFLASH_CRYPT_CNT 来烧写 FLASH_CRYPT_CNT。
espefuse.py 动将特的计数递增 1,以此来关闭加密。
5. 重置设备,设备会重新加密明分区,然后再次烧写FLASH_CRYPT_CNT 以重新启加
密。
5.6. 关闭烧写
启 flash 加密(即第次启动完成)后,使 espefuse.py 写保护 FLASH_CRYPT_CNT,
以此关闭烧写。
espefuse.py--portPORTwrite_protect_efuseFLASH_CRYPT_CNT
这样可以防进步修改 flash 加密的启和关闭。
Espressif
!/!7 16
2017.07

!
6. 预成 Flash 加密密钥"
6. 预成 Flash 加密密钥
可以在主机上预成个 flash 加密密钥,并将其烧写到 ESP32 的 eFuse 密钥块中。这实
现在主机上预先加密数据,并烧写到 ESP32,需要明烧写新 flash。
这种式有于开发,因为它消除 4 次重新烧写的限制。它还允许在启 secure boot
的情况下重新烧写,因为引导加载程序需要每次都重新烧写。
6.1. 预成 Flash 加密密钥
Flash 加密密钥是 32 个字节的随机数据。您可以使 espsecure.py 成随机密钥:
espsecure.pygenerate_flash_encryption_keymy_flash_encryption_key.bin
(该数据的随机性取决于操作系统,也是 Python 安装的随机数据源。)
或者,如果您使 secure boot,并且有 secure boot 签名密钥,那么可以成个安全
引导私有签名密钥的确定性 SHA-256 摘要,并将其作为 flash 加密密钥:
espsecure.pydigest_private-key--keyfilesecure_boot_signing_key.pem
my_flash_encryption_key.bin
(如果启 secure boot 的 reflashable 模式,则相同的 32 个字节会作为 secure boot 的
摘要密钥。)
从 secure boot 的数字签名 (signing) 密钥成 flash 加密密钥意味着您只需要存储个密
钥件。但是,这种法适于产设备。
6.2. 烧写 Flash 加密密钥
旦成 flash 加密密钥,您需要将其烧写到 ESP32 的 eFuse 密钥块。(这必须在第
次加密启动之前完成,否则 ESP32 将成个软件法访问或修改的随机密钥。)
烧写密钥到设备(只需要烧录次):
espefuse.py--portPORTburn_keyflash_encryptionmy_flash_encryption_key.bin
⚠ 注意:
此法仅于协助开发,适于产设备。如果是于产设备,请确保密钥是从质的随机数字源
成的,并且要在多个设备上共享 flash 加密密钥。
Espressif
!/!8 16
2017.07

!
6. 预成 Flash 加密密钥"
6.3. 使预成的密钥进第次烧写
烧写密钥后,按照与章节 Flash 加密初始化相同的步骤在第次启动时烧写明 image。
引导程序将使预烧录的密钥启 flash 加密,并加密所有分区。
6.4. 使预成的密钥重烧 Flash
Flash 加密在第次安全启动开启后,重新烧写加密 image 需要步额外的动操作。我
们需要预先加密想要在 flash 中新的数据。
假设这是于烧写明数据的命令:
esptool.py--port/dev/ttyUSB0--baud115200write_flash0x10000build/my-app.bin
进制 app image build / my-app.bin 被写 0x10000 。需要使此件名和偏移地址来
加密数据,如下所示:
esfsecure.pyencrypt_flash_data--keyfilemy_flash_encryption_key.bin--address0x10000-o
build/my-app-encrypted.binbuild/my-app.bin
此示命令将使提供的密钥加密 my-app.bin,并成个加密的件 my-app-
encrypted.bin。确保地址参数与您打算烧录 BIN 件的地址匹配。然后,使
esptool.py 烧写加密的 BIN 件:
esptool.py--port/dev/ttyUSB0--baud115200write_flash0x10000build/my-app-
encrypted.bin
需要其他操作或 eFuse 操作,因为数据在烧写时已经加密。
Espressif
!/!9 16
2017.07

!
7. 关闭 Flash 加密"
7. 关闭 Flash 加密
如果您启 flash 加密,下次烧写明数据时将会软启动 ESP32(设备将断
重启,并打印错误 flashreaderr,1000)。您可以通过烧写 FLASH_CRYPT_CNT eFuse 来
关闭 flash 加密。
1. 先运 makemenuconfig,取消选中 Security Features 下的 Enable flash
encryption boot。
2. 退出 menuconfig 并保存新配置。
3. 再次运 makemenuconfig,并仔细检查你是否真的取消这个选项!(如果启此选
项,则引导加载程序将在启动时即重新启加密。)
4. 运 makeflash 构建并烧写个新的引导加载程序和 app,启 flash 加密。
5. 运 espefuse.py (components/esptool_py/esptool)来禁 FLASH_CRYPT_CNT
eFuse:
6. 重启 ESP32,flash 加密应该已经被关闭,引导加载程序将正常启动。
Espressif
!/!10 16
2017.07

!
8. Flash 加密的局限"
8. Flash 加密的局限
Flash 加密可防明被读出,从防未经授权的固件读写。解 flash 加密系统的局限
性常重要:
•Flash 加密性能的强弱取决于密钥。因此,我们建议次启动时在设备上成密钥(默
认为)。如果在设备外成密钥,请确保遵循正确的过程。
•并所有数据都被加密存储。如果将数据存储在 flash,请检查您使的法(库,API
等)是否持 flash 加密。
•Flash 加密会阻攻击者解闪存的级布局。这是因为相邻的两个 16 字节 AES 块
使同个 AES 密钥。如果这些相邻的 16 字节块包含相同的内容(如空或填充
区域)时,这些块被加密时会产匹配的加密块对。这可能会让攻击者在加密设备之间
进级别较(即,判断两台设备是否运相同的固件版本)。
•出于同样的原因,攻击者可以随时知道对相邻的 16 字节块(32 字节对)是否包
含相同的内容。如果要存储的是感数据,请牢记这点。可以设计下 flash 阻攻
击者(每 16 个字节使计数字节或其他相同的值即可)。
•Flash 加密以阻攻击者修改设备的固件。要防未经授权的固件在设备上运,
请配合使 secure boot。
Espressif
!/!11 16
2017.07

!
9. Flash 加密级功能"
9. Flash 加密级功能
9.1. 加密分区标志
某些分区默认加密。您也可以将任意分区标记为需要加密:
在分区表描述的 CSV 件中有标志字段。
标志字段通常空,如果在字段中写 encrypted,则分区将标记为加密,并将此处写的
数据视为加密(就像 app 分区样):
#Name,Type,SubType,Offset,Size,Flags
nvs,data,nvs,0x9000,0x6000
phy_init,data,phy,0xf000,0x1000
factory,app,factory,0x10000,1M
secret_data,0x40,0x01,0x20000,256K,encrypted
•默认分区表都包括任何加密的数据分区。
•没有必要将 app 分区标记为加密,它们总是被视为加密的。
•如果未启 flash 加密,则 encrypted 标志起作。
•如果您希望保护 phy_init 数据防物读取或修改,可以将 phy 分区标记为加密。
•nvs 分区法被标记为加密。
9.2. 启 UART 引导加载程序加解密
默认情况下,次启动时,flash 加密过程会烧写 DISABLE_DL_ENCRYPT,
DISABLE_DL_DECRYPT 和 DISABLE_DL_CACHE:
•DISABLE_DL_ENCRYPT 在 UART 引导加载程序启动模式下禁 flash 加密操作。
•DISABLE_DL_DECRYPT 在 UART 引导加载程序模式下关闭透明解密,即使使
FLASH_CRYPT_CNT eFuse 将其使能。
•DISABLE_DL_CACHE 在 UART 引导加载程序模式下禁整个 MMU flash 缓存。
在第次启动之前,可以仅烧写某些 eFuse 特,并写保护其余的 eFuse 特(使未设
置的值 0),以保它们。如:
espefuse.py--portPORTburn_efuseDISABLE_DL_DECRYPT
espefuse.py--portPORTwrite_protect_efuseDISABLE_DL_ENCRYPT
Espressif
!/!12 16
2017.07

!
9. Flash 加密级功能"
(请注意,这 3 个 eFuse 特都通过同个写保护位关闭,因此写保护个特将起作
于这 3 个特。因此,配置特必须在写保护之前进。)
9.3. 设置 FLASH_CRYPT_CONFIG
FLASH_CRYPT_CONFIG eFuse 决定 flash 加密密钥中进块偏移“调整”的特数。详细信息
请参阅章节 Flash 加密算法。
引导加载程序的次引导始终将此值设置为最值 0xF。
可以动烧写这些 eFuse,并在次启动之前进写保护,以选择同的调整值。但是
我们推荐这样做。
当 FLASH_CRYPT_CONFIG 值为零时,我们强建议要写保护。如果此 eFuse 设置为零,
flash 加密密钥中的特会被调整,flash 加密算法等同于 AES ECB 模式。
⚠ 注意:
•写保护这些 eFuse 特以保持他们被设置作,因为 esptool.py 持写或读取加密 flash。
•DISABLE_DL_DECRYPT 未被设置(即值为 0),这会使 flash 加密效,因为具有物访问权限的攻击
者可以使 UART 引导加载程序模式(使定义存根代码)读出 flash 中的内容。
Espressif
!/!13 16
2017.07

!
10. 技术参考"
10. 技术参考
10.1. FLASH_CRYPT_CNT eFuse
FLASH_CRYPT_CNT 是个 8-bit eFuse 字段,于控制 flash 加密。Flash 加密的启或关闭
取决于此 eFuse 中设置为“1”的位数,具体如下:
•当偶数个 (0, 2, 4, 6, 8) 特被置位时:关闭 Flash 加密,任何加密数据都能被解密。
如果引导加载程序的 Enable flash encryption on boot 被启,则引导加载程序会获得这
个信息,然后当它发现未被加密的数据时会重新加密 flash。加密完成后,引导加载程序会
将 eFuse 中的另特置为'1',表示有奇数个特被置为 1。
1. 在第个明启动时,特的计数为全新值 0,引导加载程序在加密后将计数改
为 1(值为 0x01)。
2. 重烧 flash 后,特数动新为 2(值为 0x03)。重新加密后,引导程序将计数
改为 3(值为 0x07)。
3. 重烧 flash 后,特数动新为 4(值为 0x0F)。重新加密后,引导程序将计数
改为 5(值为 0x1F)。
4. 重烧 flash 后,特数动新为 6(值为 0x3F)。重新加密后,引导程序将计数
改为 7(值为 0x7F)。
•当奇数个 (1, 3, 5, 7) 特被置位时:使能透明读取加密 flash。
•当 8 个特被被置位后(eFuse 值为 0xFF):关闭透明读取加密 flash,任何加密数据
永久可访问。引导加载程序通常会检测到这种情况并停。为避免这种状态被加
载未经授权的代码,必须使 secure boot 或者写保护 FLASH_CRYPT_CNT eFuse。
10.2. FLASH 加密算法
•AES-256 在 16 字节的数据块上运。Flash 加密引擎对 32 字节块(即两个连续的
AES 块)中的数据进加解密。
•AES 算法在 flash 加密中被反转使,即 flash 加密的“加密”操作是 AES 解密,“解密”
操作是 AES 加密。这种机制是出于性能的考虑,并会影响算法的有效性。
•Flash 加密的主密钥存储在 eFuse (BLOCK1) 中,默认情况下软件能读写。
•每个 32 字节块(两个相邻的 16 字节 AES 块)共个唯的密钥进加密。这个密
钥源 eFuse 中的主密钥,与 flash 中该块的偏移进异或(“密钥调整”)。
Espressif
!/!14 16
2017.07

!
10. 技术参考"
•具体的调整取决于 FLASH_CRYPT_CONFIG eFuse 的配置。FLASH_CRYPT_CONFIG 是个 4-
bit eFuse,其中每个特使能特定范围的密钥特的异或:
- Bit1,密钥的 0-66 特被异或。
- Bit2,密钥的 67-131 特被异或。
- Bit3,密钥的 132-194 特被异或。
- Bit4,密钥的 195-256 特被异或。
建议将 FLASH_CRYPT_CONFIG 始终设置为默认值 0xF,以所有密钥特都能与块偏
移进异或。有关详细信息,请参阅章节设置 FLASH_CRYPT_CONFIG。
•块偏移(特 5-23)的 19 位与主加密密钥进异或。选择此范围有两个原因:flash
最为 16 MB(24 位),每个块为 32 字节,所以最低有效 5 位始终为零。
•19 个块偏移特与 flash 加密密钥的 256 个特之间存在特定映射,这种映射决定哪
个特与哪个块偏移进异或。有关映射的完整信息,请参阅 espsecure.py 源代码中
的_FLASH_ENCRYPTION_TWEAK_PATTERN 变。
•关于 Python 中完整的 flash 加密算法,请参阅 espsecure.py 源代码中的
_flash_encryption_operation() 函数。
Espressif
!/!15 16
2017.07

免责申明和版权公告
本中的信息,包括供参考的 URL 地址,如有变,恕另通知。
档“按现状”提供,负任何担保责任,包括对适销性、适于特定途或侵
权性的任何担保,和任何提案、规格或样品在他处提到的任何担保。本档
负任何责任,包括使本档内信息产的侵犯任何专权为的责任。本
档在此未以禁反或其他式授予任何知识产权使许可,管是明示许可
还是暗示许可。
Wi-Fi 联盟成员标志归 Wi-Fi 联盟所有。蓝标志是 Bluetooth SIG 的注册商标。
中提到的所有商标名称、商标和注册商标均属其各所有者的财产,特此声
明。
版权归 © 2017 乐鑫所有。保所有权。
乐鑫 IoT 团队
www.espressif.com
