安全启动和安全固件更新(SBSFU)11:保护链:开发 / 量产 / SECURE_LOCK 三种模式

保护链:开发 / 量产 / SECURE_LOCK 三种模式

SBSFU 深耕系列 · 11

· 原理 + 源码双线 · 以 STM32G4 为主线


上一篇回顾 · 本篇路径

第 10 篇我们把 mapping_sbsfu.icf 的每个段都讲透了------所有 PCROP / WRP / Secure User Memory 的地址都已确定。

但「地址确定 」≠「保护已启用」。SBSFU 工程实际上有 3 种「保护强度」:

  • 开发模式(DEV_MODE):保护几乎全关,方便调试
  • 量产模式(PRODUCTION):保护全开,但 RDP 留在 L1(仍可调试)
  • SECURE_LOCK 模式 :RDP 升 L2,调试口永久关闭------这一步是不可逆的

本篇要把这 3 种模式的完整状态机画出来,并讲清楚从一个模式过渡到下一个的具体步骤。

本篇核心问题

  1. 3 种模式分别启用 / 禁用了哪些保护?工程师在每个模式下能做什么?
  2. SECBOOT_OB_DEV_MODE 这个宏到底改了哪些代码行为?
  3. SBSFU 启动时的「保护检查」在不同模式下的反应是什么?
  4. 产线烧录的「最后一刀」(升 RDP-L2)什么时候打?怎么打?
  5. 如果中间某个保护配错了,怎么诊断 + 恢复?

读完后你应该能为你的产品设计完整的「开发 → 验证 → 量产」流水线。


1. 3 种模式速览表

模式 RDP PCROP WRP Secure User Mem BOOT_LOCK 调试器能干啥
DEV_MODE L1 或 L0 关闭 / 可读 关闭 / 可写 关闭 / 可见 可关 全功能:读 Flash / 改代码 / 单步调试 PCROP 区
PRODUCTION L1(仍可调试) 启用 启用 启用(G4) 启用 受限:连接 OK,但读不到 PCROP,不能改 SBSFU 段
SECURE_LOCK L2(不可逆) 启用 启用 启用 启用 完全无法连接------SWD 永久断开

⚠️ 关键不可逆点:L1 → L2 是单向的,全世界没有任何方式能把它降回 L1(除了破坏芯片)。

SBSFU 的产线流程必须:

  1. DEV_MODE 开发功能
  2. PRODUCTION 验证所有功能
  3. SECURE_LOCK 量产烧录最后一步打

一旦上 SECURE_LOCK,这块板子就不能再返厂调试。所以这步要等 100% 验证 OK。


2. DEV_MODE:开发期间的「无保护」状态

2.1 代码层面:SECBOOT_OB_DEV_MODE

打开 Projects/.../Inc/app_sfu.h,能看到这一行:

c 复制代码
/* 开发模式开关 */
#define SECBOOT_OB_DEV_MODE          /* 注释掉就是量产模式 */

打开这个宏后,SBSFU 内部很多代码行为会变化。最关键的一段在 sfu_low_level_security.c

c 复制代码
SFU_ErrorStatus SFU_LL_SECU_CheckApplyStaticProtections(void)
{
    /* 读当前选项字节 */
    HAL_FLASHEx_OBGetConfig(&obConfig);

    if (obConfig.RDPLevel != OB_RDP_LEVEL_2) {

        #ifdef SECBOOT_OB_DEV_MODE
            /* 开发模式:自动把 RDP 升到 L1(如果当前是 L0) */
            if (obConfig.RDPLevel == OB_RDP_LEVEL_0) {
                obConfig.OptionType = OPTIONBYTE_RDP;
                obConfig.RDPLevel   = OB_RDP_LEVEL_1;
                HAL_FLASH_OB_Unlock();
                HAL_FLASHEx_OBProgram(&obConfig);
                HAL_FLASH_OB_Launch();   /* 触发 reset,再次进入此函数时 RDP=L1 已生效 */
            }
            /* 注意:DEV_MODE 下不会自动升 L2 */
        #else
            /* 量产模式:RDP < L2 直接拒绝启动 */
            return SFU_ERROR_RDP_NOT_OK;
        #endif
    }

    /* 类似地处理 WRP / PCROP / SEC_SIZE 等其他选项字节 */
    ...

    return SFU_SUCCESS;
}

💡 DEV_MODE 的「自动修复」逻辑 :开发模式下,SBSFU 启动时如果发现 OB 配置不对,会自动改成正确的值 + 触发 OBL_Launch reset。第二次启动时 OB 已经正确,SBSFU 继续走流程。

这种「自我修复」设计让开发者第一次烧入 SBSFU 后只需要复位一下,剩下的让 SBSFU 自己配。

2.2 DEV_MODE 启用 / 禁用的保护对照表

保护 DEV_MODE 行为
RDP 自动升到 L1(不升到 L2)
WRP 配置但不严格------可以 OB 改
PCROP 不启用(让调试器能读 SE Code 段)
Secure User Memory 不启用(G4 上 SEC_SIZE = 0)
BOOT_LOCK 通常关闭(允许从 SRAM 启动调试)
MPU 启用,但 region 配置较松
IWDG 不启用(避免调试时 reset)
DAP 关闭 不调用
Tamper 不启用

2.3 DEV_MODE 适合干什么

  • 第一次跑通 SBSFU 框架:让 3 工程编译 + 烧录 + 启动跑起来
  • 调试 SE 内部逻辑:因为 PCROP 关闭,调试器能反汇编 SE 代码、设断点
  • 调试 Swap 算法:可以在 Swap 中途断点、检查 Flash 内容
  • 改 UserApp:业务代码调试和普通工程一样

2.4 DEV_MODE 不能做什么

  • 不能验证「真实安全性」:因为保护都关着,攻击者也能轻易读 Flash
  • 不能上量产:保护没启用就发货等于裸奔
  • 不能验证 RDP-L2 之后的行为:那是 SECURE_LOCK 模式才有

图 1·开发模式下保护处于「禁用」状态(图源:ST《SBSFU 培训-2 · 安全模式》)


3. PRODUCTION 模式:保护全开但 RDP 留 L1

3.1 怎么进入 PRODUCTION 模式

第一步:在源码里注释掉 SECBOOT_OB_DEV_MODE

c 复制代码
/* app_sfu.h */
// #define SECBOOT_OB_DEV_MODE         /* 注释掉 */

第二步:手动用 STM32CubeProgrammer 配置所有选项字节

bash 复制代码
# 一次性把所有保护打开(除了 RDP,留 L1)
STM32_Programmer_CLI -c port=SWD -ob \
    RDP=0xBB           \  # RDP = L1(还能调试)
    BOOT_LOCK=1        \
    nSWBOOT0=0         \
    nBOOT0=1           \
    SEC_SIZE1=0x10     \  # Secure User Mem 64KB
    WRP1A_STRT=0       \
    WRP1A_END=15       \
    PCROP1_STRT=0x10   \  # PCROP 起始 = 64B 块号 16,对应 0x08000400
    PCROP1_END=0x17    \  # PCROP 终点
    PCROP_RDP=1        \  # L1→L0 降级时连 PCROP 一起擦
    DBANK=0               # G4 单 bank 模式

第三步:重新烧 SBSFU + UserApp------因为去掉 DEV_MODE 宏后代码变化了。

3.2 PRODUCTION 模式下能做什么

操作 是否可行
用 ST-Link 重新烧 Flash ✓ 可以(L1 允许写 Flash)
用 ST-Link dump SE Code ✗ 不行(PCROP 拦)
用 ST-Link 读 Slot0 用户数据 ✗ 不行(RDP-L1 + Secure User Mem 拦)
单步调试 SBSFU 代码 △ 部分行(IWDG 启用会 reset)
跑 OTA 测试 ✓ 完整可行
跑 Anti-rollback 测试 ✓ 可行
跑 Tamper / 入侵测试 ✓ 可行

💡 PRODUCTION 模式的设计意图 :「保护全开 + 调试口尚可使用 」------这是「研发后期 + 客户试用 + 一致性测试」的最佳状态。

出了任何问题还能用 ST-Link 调试 / 重烧,但保护已经在工作。绝大多数 bug 在这个阶段能暴露出来

3.3 SBSFU 启动期的「保护检查」会怎样反应

PRODUCTION 模式下 SBSFU 启动检查 OB:

c 复制代码
#ifndef SECBOOT_OB_DEV_MODE
    if (obConfig.RDPLevel != OB_RDP_LEVEL_2) {
        return SFU_ERROR_RDP_NOT_OK;   /* 直接拒绝 */
    }
    if (obConfig.WRP1AStartOffset != 0 || obConfig.WRP1AEndOffset != 0x0F) {
        return SFU_ERROR_WRP_NOT_OK;
    }
    if ((obConfig.USERConfig & FLASH_OPTR_BOOT_LOCK) == 0) {
        return SFU_ERROR_BOOT_LOCK_NOT_OK;
    }
    /* ... 等等 */
#endif

注意:上面这段代码默认要求 RDP = L2,但如果你想让 PRODUCTION 模式接受 RDP-L1,需要:

  • 临时改这段检查,允许 RDP = L1 或 L2(自定义中间模式)
  • 或者保留要求 RDP = L2,那就直接进 SECURE_LOCK 模式

ST 提供的标准 SBSFU 工程默认是「DEV_MODE 或 SECURE_LOCK 」二选一,PRODUCTION 是个中间状态,需要工程师自己定义。


4. SECURE_LOCK 模式:上 RDP-L2 之后

4.1 怎么进入 SECURE_LOCK

bash 复制代码
# 假设当前是 PRODUCTION 模式(RDP=L1,其他保护已配)
# 量产线最后一刀:
STM32_Programmer_CLI -c port=SWD -ob RDP=0xCC

这一条命令瞬间发生:

  1. RDP 寄存器写 0xCC
  2. SWD/JTAG 调试口永久关闭
  3. 选项字节永久锁死------之后任何修改 OB 的尝试都会失败
  4. 复位后 CPU 从 0x08000000 起跑(BOOT_LOCK 强制)

4.2 SECURE_LOCK 模式能做什么

操作 是否可行
ST-Link 连接 ✗ 完全不行
重新烧 Flash ✗ 不行(必须先降级,但 L2 不可降级)
OTA 升级 UserApp 可以(这是 SBSFU 唯一允许的 Flash 写入路径)
Anti-rollback / Tamper / IWDG ✓ 全部工作
出厂自检 ✓(如果 UserApp 提供)
返厂维修 ✗ 只能换板子

SECURE_LOCK 是真正的「产品状态」------你卖出去的板子应该都在这个状态。

4.3 SECURE_LOCK 模式下「升级」是怎么完成的

虽然调试口关闭,但 OTA 还能工作,因为:

  • SBSFU 自己跑在芯片里,有完整 Flash 写权限(属于内部代码,不通过 SWD)
  • OTA 接收 .sfb → 写 Slot1 → Swap → 验证 → 跳 UserApp,全程内部完成
  • 不需要外部调试器介入
text 复制代码
SECURE_LOCK 模式下的更新通道:

  UserApp 业务代码
       │
       │ 通过 UART/USB/WiFi/BLE 接收 .sfb
       ▼
  UserApp 调 SE_AppliRequestUpdate()
       │
       │ 把 .sfb 写到 Slot1 (UserApp 自己直接写 Flash)
       ▼
  UserApp 触发 NVIC_SystemReset()
       │
       ▼
  SBSFU 重启
       │ 发现 Slot1 PENDING_INSTALL
       │ → Swap → 验签 → 跳新版 UserApp
       ▼
  新版本运行

图 2·SECURE_LOCK 模式状态机(图源:ST《SBSFU 培训-2 · 状态切换》)


5. 3 个模式的完整状态机

text 复制代码
                  芯片出厂态 (RDP=L0, 无保护)
                          │
                          │ 第一次烧 SBSFU + UserApp
                          ▼
                  ┌─────────────────┐
                  │  DEV_MODE        │ ◀── 开发期反复迭代
                  │  RDP=L1, PCROP=关│
                  │  Secure Mem=关   │
                  └────────┬────────┘
                           │
                           │ 1. 注释 SECBOOT_OB_DEV_MODE 宏
                           │ 2. 重新编译 + 烧录
                           │ 3. STM32CubeProgrammer 配 OB(保护全开)
                           │ 4. 但 RDP 留 L1
                           ▼
                  ┌─────────────────┐
                  │  PRODUCTION      │ ◀── 研发末期 + 量产验证
                  │  RDP=L1, 全保护开 │
                  │  调试口仍可用     │
                  └────────┬────────┘
                           │
                           │ 升 RDP 到 L2
                           │ STM32_Programmer_CLI -ob RDP=0xCC
                           ▼
                  ┌─────────────────┐
                  │  SECURE_LOCK     │ ◀── 量产 / 客户使用
                  │  RDP=L2          │
                  │  ⚠️ 不可逆       │
                  └─────────────────┘
                           │
                           │ 想回去?
                           ▼
                  ✗ 无路 --- 芯片报废或破坏性恢复

反向降级的代价

  • L2 → L1:不可能
  • L1 → L0:全片擦除(包括 PCROP 区,PCROP_RDP=1 时)
  • L0 → 出厂:擦完就行

所以 PRODUCTION → SECURE_LOCK 这一步是「最后一刀」,要在所有功能都验证 OK 后才打。


6. 量产烧录流水线(实务建议)

完整的产线烧录流程:

text 复制代码
工厂烧录工位 (假设有 1000 块板子):

  ┌────────────────────────────────────────────────────────────┐
  │  Stage 1: 全片擦 + 烧 SBSFU_UserApp.bin                       │
  │    STM32_Programmer_CLI -c port=SWD -e all                  │
  │    STM32_Programmer_CLI -c port=SWD -w SBSFU_UserApp.bin    │
  │    时间:~5 秒/板                                             │
  └────────────────────────────────────────────────────────────┘
                          │
                          ▼
  ┌────────────────────────────────────────────────────────────┐
  │  Stage 2: 配置 Option Bytes(保护全开 + RDP=L1)              │
  │    STM32_Programmer_CLI -ob RDP=0xBB BOOT_LOCK=1 ...        │
  │    时间:~2 秒/板                                             │
  └────────────────────────────────────────────────────────────┘
                          │
                          ▼
  ┌────────────────────────────────────────────────────────────┐
  │  Stage 3: 上电自检(开 board + 按测试按钮 + 等 LED 绿)         │
  │    - 检查 SBSFU 启动到 UserApp                                │
  │    - 检查关键外设功能                                          │
  │    - 检查产品功能(业务自测)                                   │
  │    时间:~30 秒~5 分钟/板                                      │
  │    任何失败 → 标记为「待返修」,不进 Stage 4                     │
  └────────────────────────────────────────────────────────────┘
                          │
                          ▼
  ┌────────────────────────────────────────────────────────────┐
  │  Stage 4: 「最后一刀」 --- 升 RDP 到 L2                          │
  │    STM32_Programmer_CLI -c port=SWD -ob RDP=0xCC            │
  │    时间:~1 秒/板                                              │
  │    这一步执行完,板子立刻进 SECURE_LOCK 模式                     │
  └────────────────────────────────────────────────────────────┘
                          │
                          ▼
                       发货!

💡 几个产线实务建议

Stage 3 必须严格------一旦 Stage 4 完成,板子就不能调试了。所以 Stage 3 的自检要尽量覆盖

Stage 4 应该有「审核机制------比如要求两个工位人员复核测试结果再触发 RDP=L2

保留 Stage 2 状态的板子------这是「待客户验证」时的最佳折中:保护已开但还能返厂调试

产品手册要明确 :客户拿到的板子在 SECURE_LOCK 状态,所有调试 / 维修都需要厂家


7. 模式切换时的「中途异常」处理

7.1 「我烧完 SBSFU 后没法跑 OTA」

最常见原因:Option Bytes 没配对。例如:

  • WRP 配错了,SBSFU 没法擦写 Slot1
  • Secure User Memory 起点不对,SBSFU 启动失败
  • BOOT_LOCK 没启用,复位从其他地方启动

诊断方法:

bash 复制代码
# Dump 当前 OB
STM32_Programmer_CLI -c port=SWD -ob displ

# 输出示例:
# RDP            : 0xBB
# WRP1A_STRT     : 0x00
# WRP1A_END      : 0x0F
# PCROP1_STRT    : 0x10
# PCROP1_END     : 0x17
# SEC_SIZE       : 0x10
# BOOT_LOCK      : 1
# ...

把上面输出和预期值对比。

7.2 「我已经升 RDP-L2 了,发现 SBSFU 有 bug,能修吗?」

坏消息:板子完全无法调试,也无法重烧 SBSFU。

好消息 :只要 SBSFU 还能跑(哪怕功能不全),通过 OTA 仍然可以升级 UserApp------UserApp 业务代码可以解决很多问题。

真坏消息:如果 bug 在 SBSFU 自己里(无法启动到 UserApp):板子变砖,只能换。

教训:SBSFU 是「信任根」,任何 bug 都是产品级灾难。一定要在 DEV / PRODUCTION 模式下充分测试。

7.3 「DEV_MODE 烧上后跳不到 UserApp 怎么办」

可能原因:

  • UserApp 的链接地址不对(不是 0x08010200)
  • UserApp 的 Reset_Handler 改写时钟,导致 SBSFU 配的 PLL 失效
  • UserApp 没有自己的 SCB->VTOR 设置

诊断方法:

  • 在 SBSFU 的 SFU_BOOT_LaunchUserApp() 前加 printf,看跳转地址
  • 在 UserApp 的 Reset_Handler 第一条加 GPIO 拉高,看是否进来
  • 用 ST-Link 在跳转后立刻 halt,看 PC 在哪

8. 安全测试 checklist:发货前必须验证

进入 SECURE_LOCK 之前,至少要验证完这些场景:

text 复制代码
[ ] 正常启动 → UserApp 运行 → reset → 再次启动 OK
[ ] 故意改 Slot0 一个字节 → SBSFU 拒绝跳 UserApp
[ ] 故意改 Slot1 上的 .sfb header → SBSFU 拒绝装新 FW
[ ] OTA 升级新 FW → 装上 → 运行新版
[ ] OTA 升级中途断电 → 重新上电 → 恢复正确状态(旧版或新版)
[ ] OTA 升级新 FW → 新版自检失败 → SBSFU 回滚到旧版
[ ] 用比当前版本号低的 .sfb → SBSFU 拒绝装(anti-rollback)
[ ] 用错误的私钥签的 .sfb → SBSFU 验签失败 → 拒绝
[ ] 拔 ST-Link → 板子继续正常运行(无 ST-Link 启动 OK)
[ ] Tamper 检测:物理拆机 / 短接 Tamper 引脚 → 备份域擦除
[ ] IWDG 检测:让 SBSFU 卡 1 秒 → 自动 reset
[ ] PCROP 检测:在 UserApp 里读 SE Code 段地址 → HardFault
[ ] MPU 检测:UserApp 写 SBSFU RAM → HardFault

每一项都通过,再敲下 RDP=0xCC 的命令。


9. 「灰度切换」策略:分批升 RDP-L2

对于大批量出货,建议「分批 SECURE_LOCK」策略:

text 复制代码
- 第一批 100 块板子 → PRODUCTION 模式(RDP=L1)→ 送客户「试用版」
- 收集 1-2 周客户反馈、有问题用 ST-Link 调试 / 重烧
- 改完所有 bug,再做第二批
- 第二批 1000 块 → PRODUCTION → 送客户「正式版」
- 客户反馈 OK 1 个月
- 第三批开始 → 直接 SECURE_LOCK 出货

虽然第一批没上 SECURE_LOCK,但物理隔离 + 测试合同 + 用户协议能控制风险。


10. 第 11 篇 Checklist

读完本篇你应该能不查资料回答:

  • ☐ DEV_MODE / PRODUCTION / SECURE_LOCK 3 个模式分别启用 / 禁用了哪些保护?(§1)
  • ☐ SECBOOT_OB_DEV_MODE 宏控制什么代码行为?(§2.1)
  • ☐ DEV_MODE 适合干什么、不能干什么?(§2.3 / §2.4)
  • ☐ 从 DEV_MODE 切到 PRODUCTION 需要做哪 3 件事?(§3.1)
  • ☐ 为什么 PRODUCTION 是个「中间状态」?SBSFU 标准工程默认不接受怎么办?(§3.3)
  • ☐ SECURE_LOCK 下还能干什么?还能 OTA 升级吗?(§4)
  • ☐ 量产烧录的 4 个 Stage 分别是什么?为什么 Stage 4 要独立?(§6)
  • ☐ 已经 SECURE_LOCK 的板子发现 bug 怎么办?(§7.2)

下一篇预告

《12 · 调试 / 移植 / 生产实务》------这是系列最后一篇,集中讲 3 件最「工程 」的事:① 调试技巧:怎么不复位调试 SBSFU 内部?怎么用 trace 看 SE 调用过程?② 移植:跨芯片移植的具体 step-by-step(G4 → F4 / L4 / H7)。③ 生产:签名服务器怎么搭?产线烧录工具怎么做?密钥怎么管理?读完那篇你应该能从「纸面理解 」走到「实际落地」。


本文示意图源 © STMicroelectronics,引用自 ST 官方培训资料 LAT1087/LAT1088 系列。文字部分为原创,欢迎转载并保留出处。

相关推荐
TOWE technology2 小时前
同为科技雷电防护产品,构筑全场景电气安全防线
网络·科技·安全·防雷产品·防雷工程·防雷施工·防雷设计
2601_957787583 小时前
短视频矩阵风控对抗技术:星链引擎的账号安全防护体系深度解析
线性代数·安全·矩阵
@insist1233 小时前
信息安全工程师-测评核心知识框架与关键流程(下篇)
网络·安全·软考·信息安全工程师·软件水平考试
DianSan_ERP3 小时前
抖店订单接口中消费者信息加密解密机制与安全履约全解析
前端·网络·数据库·后端·安全·团队开发·运维开发
侃谈科技圈3 小时前
硬件确认与助记词备份正在成为钱包安全管理的重要环节
安全·区块链
JiaWen技术圈6 小时前
FRP TLS 安全传输的配置指南
安全
盟接之桥6 小时前
制造业场景 | 电子数据交换(EDI)软件|AS2协议
大数据·网络·安全·汽车·制造
JiaWen技术圈6 小时前
主流非 JWT 式 Access Token 方案
前端·安全
云水一下7 小时前
华为防火墙安全区域与NAT实战:基于eNSP的企业边界网完整部署
安全·华为·nat·下一代防火墙