在esp-idf中复制出(/esp/esp-idf/examples/security/flash_encryption)demo文件,详细加密描述参考乐鑫文档Flash加密
一、开发模式
在开发过程中,可使用 ESP32 内部生成的密钥或外部主机生成的密钥进行 flash 加密。
在开发模式下不会阻止修改和读取加密的 flash 内容。
1、使用 ESP32 生成的密钥
1.1检查 ESP32 flash 加密状态
在做加密实验之前,且确保模组没有做任何的加密,要检查您ESP32 设备上是否启用了 flash 加密,请执行以下操作之一:
(1)将应用示例 security/flash_encryption 烧录到设备上。此应用程序会打印 FLASH_CRYPT_CNT eFuse 值,以及是否启用了 flash 加密。
(2)查询设备所连接的串口名称,在以下命令中将 PORT 替换为串口名称后运行:
espefuse.py -p PORT summary
1.2在项目配置菜单,执行以下操作进行flash加密
(1)启动时使能 flash 加密,选择加密模式 (开发模式)
进入idf.py menuconfig
(2)选择 UART ROM 下载模式 (默认是启用)
(3)选择适当详细程度的引导加载程序日志
接着保存配置并退出。
1.3运行以下命令来构建和烧录完整的镜像
该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。
idf.py -b 921600 flash monitor -p /dev/ttyUSB0
烧录完成后,ESP32 将重置。“Development”模式下启用flash加密后,首次输出显示启用flash加密的过程(这次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,需要等待一会):
可以看出打印出分区表信息,CRYPT_CONFIG设置为0xF,以及三个加密的分区和偏移量,最后加密完成设备重启。
之后,应用程序在运行时解密并执行命令。启用 flash 加密后,在下次启动时输出将显示已启用 flash 加密,样例输出如下:
检查设备加密状态,FLASH_CRYPT_CNT值为1,表示加密成功。
启动flash加密后默认加密nvs分区,可在menuconfig中设置是否启用nvs加密。我在这里出现了一个小问题,在第二次启动后flash显示加密,然后nvs初始化未成功,(返回0x1117提示 NVS密钥分区已损坏,可能是之前此分区烧录过其他密钥),设备重启。
解决方式是擦除所有分区
idf.py erase_flash
再重新烧录。(注意:在开发模式下修改了应用程序重新烧录要使用以下命令对新的明文应用进行加密写入:
idf.py -p PORT encrypted-flash monitor
),不然以明文方式烧录会导致设备一直重启。
2、关闭flash加密
为了让同一个模组验证一遍使用主机生成的密钥,关闭此模组的flash加密
首先用
idf.py erase_flash -p /dev/ttyUSB0
擦除所有分区
对于开发模式下的 flash 加密,可以通过烧录 FLASH_CRYPT_CNT efuse 来关闭加密。每个芯片仅有 3 次机会,请执行以下步骤:
1、在 项目配置菜单 中,禁用 启动时使能 flash 加密 选项,然后保存并退出。
2、再次打开项目配置菜单,再次检查你是否已经禁用了该选项,如果这个选项仍被启用,引导加载程序在启动时将立即重新启用加密功能。
3、在禁用 flash 加密后,通过运行 idf.py flash 来构建和烧录新的引导加载程序和应用程序。
此时不用上电打开串口跑程序,因为仍然是加密状态,设备一直重启,紧接着下一步
4、使用 espefuse.py (在 components/esptool_py/esptool 中)以关闭 FLASH_CRYPT_CNT,运行:
espefuse.py burn_efuse FLASH_CRYPT_CNT
输出信息如下:
接着输入BURN,提示FLASH_CRYPT_CNT关闭成功
此时重置 ESP32,打开串口,flash 加密应处于关闭状态,引导加载程序将正常启动。设备以未加密状态运行。
3、使用主机生成的密钥
步骤与使用 ESP32 生成的密钥方式基本相同,只是在项目配置前多了两步
1、通过运行以下命令生成一个随机密钥:
espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin
2、在第一次加密启动前,使用以下命令将该密钥烧录到设备上,这个操作只能执行 一次。
espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin
后面的步骤与上面1.2配置项目一样,输出同样的结果,只是FLASH_CRYPT_CNT的值会发生改变,由1变为3再变为7了。
二、发布模式
在发布模式下,UART 引导加载程序无法执行 flash 加密操作,只能 使用 OTA 方案下载新的明文镜像,该方案将在写入 flash 前加密明文镜像。
重新操作上述flash解密操作,再按照开发模式下步骤进行加密,区别在于在项目配置菜单时选择发布模式
重新烧录(idf.py flash monitor)后发布模式运行界面如下:
查看FLASH_CRYPT_CNT的值为127
在发布模式下没有禁用UART ROM下载模式就无法用加密方式烧录程序了,可以通过明文方式烧录,由于已经加密,明文数据的 flash 会使 ESP32 无法正常启动,烧录进去之后设备一直重启。
一旦在发布模式下启用 flash 加密,引导加载程序将写保护 FLASH_CRYPT_CNT eFuse。由于是使用 ESP32 生成的密钥,主机上没有这个副本,此设备无法关闭flash加密,UART 引导加载程序无法执行 flash 加密操作,这个设备再烧录程序也跑不起来,无法通过通过串口更新加密 flash,也就是作废了,以后只能使用 OTA 方案 对字段中的明文进行后续更新。
在制造和生产过程中,出于安全考虑,固件下载模式不应有权限访问 flash 内容。所以在生产过程中设置为发布模式,并且禁用UART ROM下载模式以防止物理读取加密的 flash 内容。
同上的发布模式操作,只是要选择禁用UART ROM下载模式,要注意的是该选项仅在 CONFIG_ESP32_REV_MIN 级别设置为 3 时 (ESP32 V3) 可用。默认选项是保持启用 UART ROM 下载模式,然而建议永久禁用该模式,以减少攻击者可用的选项。
如果生产设备不需要 UART ROM 下载模式,那么则该禁用该模式以增加设备安全性。这可以通过在应用程序启动时调用 esp_efuse_disable_rom_download_mode() 来实现。
注意:只有revision版本设置为rev3时才能去禁用UART ROM download mode。
更换一块新模组在设置之后再烧录进设备,等待发布模式加密完成,将IO0拉低重新上电发现终端显示下载模式被禁用,至此,设备不能通过串口下载了。只能通过终端查看log信息。
版权归原作者 蜗牛先森i 所有, 如有侵权,请联系我们删除。