当前位置: 首页 > news >正文

MCU程序加密保护(一)闪存读写保护法 加密与解密

MCU(微控制器单元)的加密方法可以从硬件、软件和通信协议三个层面来理解。以下是常见的MCU加密手段,按类型分类说明:

针对目前 STM32 系列微控制器在程序加密保护方面手段单一、保护效果有限的问题,本文介绍并分析了四种常用的程序保护方法:

  1. 闪存读写保护

  2. 芯片唯一 ID 验证

  3. 外接加密芯片

  4. 引导程序加密(Bootloader 加密)

实际在 STM32 开发板上的测试表明,合理组合多种保护机制,能显著增强芯片程序与数据的安全性,有效防止闪存程序被读取、拷贝或篡改,为嵌入式系统提供更可靠的安全保障。 

1 闪存读写保护法

STM32 微控制器提供了闪存读写保护的功能,

用来防止对闪存的非法访问。 闪存读写保护功能概述:

读保护(RDP)

  • 通过修改 Option Bytes 中的 RDP 位来启用。

  • 启用后,Flash 只能被内部正常执行的程序读取,无法通过 JTAG/SWD 调试接口或从 RAM 启动的程序读取。

  • 解除读保护会触发整片 Flash 擦除,防止逆向工程与调试工具破解。

  • 以 STM32L1 系列为例,RDP 分为 3 个等级,不同等级对应不同的安全强度。

等级描述
0无保护(默认)。可以通过 JTAG/SWD 或从 RAM 启动的程序任意读取 Flash。
1Flash 受保护,防止由调试器(JTAG/SWD)直接读取,也不能通过在 RAM 中加载执行程序来读取。
解除 Level 1 保护将触发全片擦除。
2最严格保护——禁用所有调试功能。
一旦设为 Level 2,不可复原,需谨慎使用。

写保护(WRP)

  • 通过在 Option Bytes 中设置 WRP 位来启用。

  • 启用后,对被保护页的任何写或擦除操作都会被硬件阻止,并在状态寄存器中产生错误标志。

  • 可以防止恶意修改中断向量表或关键代码区域。

优缺点对比:

优点

由硬件层面直接提供,成本为零,易于配置。

能有效防止通过调试接口的非法读写

缺点

单一的读/写保护难以抵抗高级物理攻击或侧信道分析。

需要与软件层面的校验(如 CRC、HASH)或更高级的加密方法(如外部加密芯片、Bootloader 加密)组合,才能构建更完善的防护体系。

实施的方法如下,下面以 STM32G4 系列为例,分别介绍如何通过 ST-Link/CubeProgrammer 工具以及 运行时(HAL)编程 两种方式来启用 Flash 的读写保护(RDP 和 WRP)。

方法一:通过 STM32CubeProgrammer 界面设置

打开 CubeProgrammer

启动 STM32CubeProgrammer,选择 “ST-Link” 连接。

读取当前 Option Bytes

在左侧菜单选择 “Option Bytes”

点击 “Read”,查看当前 RDP(Read Protection)和 WRP(Write Protection) 配置。

配置读保护(RDP)

“Read protection” 下拉框中选择:

Level 0:无保护

Level 1:Flash 只允许内部执行读取

Level 2:全部调试接口禁用(不可逆)

推荐一般项目选 Level 1

配置写保护(WRP)

“Write protection” 区域,勾选你要保护的 Flash 扇区(Page)。

比如要保护第 0~3 扇区,就勾选对应页号。

写入并重启

点击 “Apply”,CubeProgrammer 会提示需要复位芯片以生效。

确认后,设备重启,Option Bytes 即更新完毕。

方法二:在用户代码中动态配置(HAL 库示例)

如果希望在程序首次运行时,或通过 Bootloader 进行保护设置,可以在固件内部调用 HAL API 来修改 Option Bytes。

/*** @brief  启用 RDP Level1 并对指定扇区启用写保护* @note   必须在系统启动早期执行,且芯片复位后才生效*/
void Protect_Flash(void)
{HAL_FLASH_Unlock();HAL_FLASH_OB_Unlock();/* 1) 读保护 → Level1 */FLASH_OBProgramInitTypeDef OBInit = {0};OBInit.OptionType = OPTIONBYTE_RDP;OBInit.RDPLevel   = OB_RDP_LEVEL_1;if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {/* 错误处理 */}/* 2) 写保护 → 保护第 0~15 KB(页 0~15) */memset(&OBInit, 0, sizeof(OBInit));OBInit.OptionType = OPTIONBYTE_WRP;OBInit.WRPState   = OB_WRPSTATE_ENABLE;OBInit.WRPPage    = OB_WRP_PAGES0TO3   | OB_WRP_PAGES4TO7   | OB_WRP_PAGES8TO11  | OB_WRP_PAGES12TO15;if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {/* 错误处理 */}HAL_FLASH_OB_Lock();HAL_FLASH_Lock();//    /* 复位生效 */
//    NVIC_SystemReset();
}

 其次你会发现程序也烧写不进去。此时目标也达成。

我们说了加密,那如何解密呢?问题在于每次切换RDPLevel 1到0的过程中的时候,会将flash的内容全部擦除。因此这是解密的难点之一。

我们引入思考点一,针对闪存读写保护法这类内容也就是寄存器置位,如果你要切换RDP1到RDP0 的过程伴随着一个问题,STM32 上的 Read-Out Protection(RDP)并不是真正的“加密”,而是一种硬件级的“只读保护”机制——它保证 任何 试图“解开”这层保护的操作(也就是把 RDP 从 Level 1 降回 Level 0),都会触发一次整片 Flash 的 不可逆擦除,从而根本不可能在芯片上恢复出原来的固件!!!

一旦启用 RDP Level 1,就不可能在器件内“解密”或“读取” Flash 内容;任何试图取消保护的行为都会把所有数据抹掉。

为什么不能“解密”现有固件???

STM32 的 RDP 设计上就是「不可逆保护」:降级就擦除。

Flash 中的代码以明文形式存储,Option Bytes 保护只是阻止「直接」访问,但并不做真实的加密。

一旦需要「访问明文」,只能通过内部执行(CPU 跳转),而不是通过调试器或外部读口。

因此问题点来了!!!我们要做的是,在启用了 RDP Level 1 以后,所有基于 JTAG/SWD外部调试器 的直接读 Flash 操作都会被阻止——硬件层面上不可能再通过外部工具把 Flash 整片“拷”出来。不过,RDP Level 1 并不影响 MCU 自身程序对 Flash 的正常读取;换句话说,你只要在芯片内跑一段用户代码,通过 UART/CAN/USB 等总线把 Flash 内容“转发”出去,就能获得完整的二进制镜像。

20250513 23:38待补全。。。

相关文章:

  • nginx配置反向代理支持CORS跨域请求
  • Leetcode (力扣)做题记录 hot100(49,136,169,20)
  • 关于vue 本地代理
  • Cookie、 Local Storage、 Session Storage三种客户端存储方式
  • Model Context Protocol -MCP创建Agent - Part1
  • 力扣-1.两数之和
  • ubuntu---100条常用命令
  • 基于AI的报告平台
  • [SAP] 通过事务码Tcode获取程序名
  • Linux字体遍历 获取支持的unicode范围
  • Windows Java gRPC 示例
  • 音频特征工具Librosa包的使用
  • 在Window上面添加交叉编译链 MinGW+NDK
  • jackson-dataformat-xml引入使用后,响应体全是xml
  • 3.1 泰勒公式出发点
  • 9.9 Ollama私有化部署Mistral 7B全指南:命令行交互到API集成全流程解析
  • “端 - 边 - 云”三级智能协同平台的理论建构与技术实现
  • 组合问题(多条件)
  • AWS IoT Core自定义域名配置实战指南
  • 某实战项目登录口处的渗透测试
  • 习近平致电祝贺阿尔巴尼斯当选连任澳大利亚总理
  • 迪奥部分客户数据遭泄露,公司称正持续展开调查
  • 牧原股份子公司与养殖户种猪买卖纠纷案一审胜诉
  • 最高降价三成,苹果中国iPhone开启大促销,能拉动多少销量?
  • 数说母亲节|全球11亿女性进入更年期,“不是忍忍就好”
  • 宣布停火后,印控克什米尔地区再次传出爆炸声