ESP32的flash加密过程及实现

本文详细介绍了ESP32的Flash加密过程,包括开发模式和生产模式的加密方法,强调了加密的一次性性质以及加密后的固件烧录变化。在开发模式下,加密可以通过ESP32随机生成的密钥或自定义密钥进行,并通过idf.py脚本配置和烧录。生产模式加密则更为严格,一旦加密,只能通过OTA更新程序。
摘要由CSDN通过智能技术生成


前言

       一个项目完成之后,为了防止二次烧录或固件盗版,通常会进行程序加密,就好像STM32的flash写都保护、唯一ID程序加密类似。
       乐鑫给我们提供了flash加密的方案,flash 加密功能用于加密与 ESP32 搭载使用的片外 flash 中的内容。启用 flash 加密功能后,固件会以明文形式烧录,然后在首次启动时将数据进行加密。因此,物理读取 flash 将无法恢复大部分 flash 内容。


一、注意

       请熟读这篇文章再尝试去做加密实验,因为加密是一次性的,可能会导致因为加密使模组变 “软砖”,加密执行之后,将无法使用 flash_download_tool 工具进行固件烧录,你会得到这样的提示:
 
在这里插入图片描述

二、flash加密过程

假设 eFuse 值处于默认状态,且固件的引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下:

  • 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。

  • 固件的引导加载程序将读取 FLASH_CRYPT_CNT eFuse 值(0b0000000)。因为该值为 0(偶数位),固件的引导加载程序将配置并启用 flash 加密块,同时将 FLASH_CRYPT_CONFIG eFuse 的值编程为 0xF。

  • 固件的引导加载程序使用 RNG(随机数生成)模块生成 AES-256 位密钥,然后将其写入 flash_encryption eFuse 中。由于 flash_encryption eFuse 已设置编写和读取保护位,将无法通过软件访问密钥。Flash 加密操作完全在硬件中完成,无法通过软件访问密钥。

  • Flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。

  • 固件引导加载程序将在 FLASH_CRYPT_CNT (0b0000001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数个比特位。

  • 对于 开发模式,固件引导加载程序仅设置 DISABLE_DL_DECRYPTDISABLE_DL_CACHE 的 eFuse 位,以便 UART 引导加载程序重新烧录加密的二进制文件。此外, FLASH_CRYPT_CNT 的 eFuse 位不受写入保护。

  • 对于 发布模式,固件引导加载程序设置 DISABLE_DL_ENCRYPTDISABLE_DL_DECRYPTDISABLE_DL_CACHE 的 eFuse 位为 1,以防止 UART 引导加载程序解密 flash 内容。它还写保护 FLASH_CRYPT_CNT eFuse 位。要修改此行为,请参阅 启用 UART 引导加载程序加密/解密。

  • 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。
           简而言之就是:加密的程序启动之后,首先会由程序引导进行加密。加密需要时间,加密成功之后,会把FLASH_CRYPT_CNT位从0x0变为1或0xf,最后才开始执行用户程序。

三、加密模式

       Flash加密分两种模式,一个是开发模式、另一个则是生产模式。

3.1 开发模式加密

       既然是加密,那肯定需要密钥,乐鑫也给我们提供了两种密钥的加密或生成方法:

3.1.1 使用ESP32生成的密钥加密

       使用这个加密方法的话,密钥是唯一的,而且不可见。密钥不会被保存到系统文件当中,只会随机生成并烧录到efuse分区。
注意:
       在做加密实验之前,且确保模组没有做任何的加密,加密状态的查询指令为,(PORT为串口的端口号):

espefuse.py -p PORT summary

在这里插入图片描述
       本文将以hello_world例程作为例子进行加密,在hello_world目录下运行:

idf.py menuconfig

执行以下操作:

  • 启动时使能 flash 加密
  • 选择发布模式 (注意一旦选择了发布模式,DISABLE_DL_ENCRYPTDISABLE_DL_DECRYPT eFuse 位将被编程为在 ROM 下载模式下禁用 flash 加密硬件)
  • 选择 UART ROM 下载模式(推荐永久性禁用) (注意该选项仅在 CONFIG_ESP32_REV_MIN 级别设置为 3 时 (ESP32 V3) 可用。)默认选项是保持启用 UART ROM 下载模式,然而建议永久禁用该模式,以减少攻击者可用的选项。
  • 选择适当详细程度的引导加载程序日志
  • 保存配置并退出
    在这里插入图片描述
    然后直接运行:
idf.py flash monitor

加密成功截图:
在这里插入图片描述
然后我们可以看一下:FLASH_CRYPT_CNT
在这里插入图片描述
可以看到,FLASH_CRYPT_CNT的值被置为 1;就表示已经成功加密。

3.1.2 使用自主生成的密钥进行加密

       使用自主生成的密钥其实就是多了烧录密钥这一步,密钥的生成指令:

espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin

我建议把密钥保存到单独的文件当中,防止误删。生成密钥之后,使用以下指令烧录密钥:

espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin

下一步,就可以根据3.1.1中的配置烧录

3.2 生产模式加密

       使用开发模式,依旧是可以使用idf.py脚本进行烧录,只不过有次数限制,但是可以关闭加密:

espefuse.py burn_efuse FLASH_CRYPT_CNT

但是生产模式的加密烧录是没有重复烧录机会的,通常在量产时才会用,因为这是一次性的,烧录之后只能通过OTA来进行程序升级。它的配置如下:
在这里插入图片描述
直接使用:

idf.py flash monitor

为此,博主的模组就成了“软砖”:
在这里插入图片描述

更多信息请转跳:

https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/security/flash-encryption.html#flash-encryption-status
欢迎关注:安信可科技

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值