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

安全存储之 SAES+HUK 使用技巧和常见问题 LAT1543

关键字:AES,SAES, HUK, DHUK, 安全存储

引言

近年来,嵌入式设备信息安全被越来越多地提及,从智能穿戴产品、智能工业设备到物联网产品都对设备信息安全提出了要求,比如基础的安全启动,安全升级,调试端口保护等,一些应用场景还会涉及安全存储的需求。一些相关的信息安全技术标准中也会提及对设备安全存储能力的要求,例如针对物联网设备的 EN303645 ,针对工业自动控制系统中的设备安全的 IEC62443-4-2 。安全存储的目标包括实现对敏感数据或用户数据的保护,对机密数据例如密钥的保护等等。

为了更好地满足安全存储需要,方便客户更容易地实现安全存储的目标,STM32 的新系列产品中增加了相关硬件,来更好地支持安全存储功能的实现,其中最典型的硬件特性就是安全AES 模块(Secure AES)和硬件唯一密钥模块(Hardware Unique Key),分别简称 SAES 和 HUK。本文将首先对 SAES 的主要特性做简要介绍,然后介绍几个有关 SAES 和 HUK 实现安全存储的典型用例,最后讨论几个 SAES 和 HUK 使用中的常见问题和解决方法。

1 SAES 主要特性

STM32 的几个较新的系列中都增加了 SAES 和 HUK 硬件,在目前已经发布的产品中支持 SAES 和 HUK 的主要包括:STM32U5系列,STM32WBA 系列,STM32H7S系列,STM32H5 系列,STM32N6系列等(这里指的都是其中带有硬件 crypto 的型号)。

SAES 是独立于普通 AES 外设的另一个安全 AES 加解密引擎,也就是说在这些系列中除了原有的 AES 外设之外,新增加了另一个 SAES 硬件模块。SAES之所以叫做 Secure AES,它和普通 AES 相比主要有以下几点不同:

  • SAES 的加解密单元是安全核,采用更安全的设计,在硬件算法实现上就能够抵御侧信道攻击及错误注入攻击。当然,由于加入了防护,它的运算效率没有普通 AES 硬件高,同样的算法需要更多的时钟周期来完成。
  • SAES 增加了密钥来源的选择,除了传统的通过软件写入密钥寄存器,还支持硬件密钥,比如 HUK,BHK,AHK。硬件密钥在发生入侵事件时将被自动清除或者锁定(比如数值保持全 0 或者无法使用)

软件可以选择硬件密钥中的一个或者其中两个的组合作为密钥,对数据进行加解密,例如需要加密某个数据的时候,可以使用 DHUK,或者 BHK,或者 DHUK⊕BHK 作为密钥来源,支持 AHK 的系列中也可以选择 AHK 或者 DHUK⊕AHK。

1.1SAES 支持的几种硬件密钥及其特点

HUK:Hardware Unique Key

  • 出厂时芯片自带的硬件唯一密钥,长度为 256bit,我们把它称为 RHUK,即 Root HUK, RHUK 通过私有总线连接到 SAES。CPU、DMA、调试端口等都无法获取密钥内容,但是 SAES 可以使用 HUK 进行加解密操作。
  • SAES 的加解密并不会直接使用 RHUK,SAES 内部带有一个密钥派生单元,从RHUK 生成派生密钥 DHUK(Derived HUK),实际加解密操作用到的是 DHUK。DHUK 的生成依赖其他一些系统配置和状态,比如密钥使用模式,当前 TrustZone的安全/非安全上下文等,因此系统中可以使用多个不同的 DHUK。
  • 在部分系列中(例如 STM32H5,STM32H7S,STM32N6),DHUK 的密钥派生过程还增加了时域隔离保护(基于 HDPL 隐藏保护级别)和防重放攻击保护(基于EPOCH 单向计数器)。

          时域隔离保护:当不同阶段的软件在执行时,可以设置 HDP 保护为不同的级别,例如第一级 bootloader 代码运行在 HDPL1,第二级 bootloader 运行在HDPL2,App 运行在 HDPL3。HDPL 处于不同级别时,DHUK 将派生出不同的密钥。这意味着各个不同阶段的软件用 DHUK 加密数据时将使用不同的密钥。

          防重放攻击保护:系统中有 EPOCH 单向计数器,如果芯片的 Product State从 Closed 状态经过 Debug Authentication 流程回到 Open 状态,EPOCH 单向计数器会自动增加。由于 EPOCH 的值也会影响 DHUK 的派生,这样只要发生了产品的状态回退,那么回退之前存储的所有使用 DHUK 参与加密的数据都无法再被解密,因为 DHUK 在更新的 EPOCH 下会产生不同的密钥值。

BHK: Boot Hardware Key

  • BHK 是由软件写入后备域寄存器 0-7 的密钥,通常由软件在启动阶段写入。
  • BHK 写入后可以被锁定,锁定后的 BHK 只能通过私有总线导入 SAES,而无法被软件读取。

AHK:Application Hardware Key

  • STM32H7S 系列带有 AHK 功能,AHK 数据来自 OBK 存储区对应每个 HDP level 的前 8 个 index 的数据,OBK Index0-7 的数据只能写,不能读。
  • 应用程序可以将需要操作的密钥写入 OBK index0-7,作为 AHK,并配置 SAES 选择AHK 作为密钥来源

上述这些硬件密钥以及锁定后的 BHK 只能被 SAES 使用,而不能被软件(包括 CPU,DMA,调试端口等)访问。DHUK 相当于每颗芯片都预置了不可知的密钥,但是应用可以使用这些派生密钥对数进行加解密,BHK 可以看作是 bootloader 才知道的密钥,而 AHK 则是用户自己写入的已知的硬件密钥,但是所有软件运行过程中都无法看到这个密钥的内容。

1.2 SAES 及硬件密钥主要特性

图 1 图 2 图 3 图 4 分别给出了 STM32U5/WBA,STM32H5,STM32H7S 和 STM32N6 的 SAES 单元与硬件密钥的示意图。

图1. STM32U5/WBA SAES 与 HUK/BHK

图2. STM32H5 SAES 与 HUK/BHK

图3. STM32H7S SAES 与 HUK/BHK/AHK

图4. STM32N6 SAES 与 HUK/BHK

Error! Reference source not found.总结了几个系列产品中 SAES 和硬件密钥的主要特性及差异

表1. 几个系列产品中 SAES 和硬件密钥的主要特性及差异

1.2.1 几种硬件密钥及其使用场景

从前文可以看到 SAES 可以选择几种不同的硬件密钥来源,接下来介绍几种硬件密钥的特点,有什么不同,以及通常什么应用场景下可以考虑选择哪种硬件密钥或者硬件密钥的组合。

1.2.2 DHUK vs. AHK vs. BHK

表 2 总结了三种硬件密钥的异同以及主要使用场景。

表2. 几个系列产品中 SAES 和硬件密钥的主要特性及差异

1.2.3 DHUK⊕AHK, DHUK⊕BHK

在表 2 描述的场景 1 的基础上,有时客户会希望加密密钥不是完全来自于不可知的硬件密钥,而是能有自己可控的部分数据的参与。

对于这样的需求,在支持 AHK 的系列上就可以考虑使用 DHUK⊕AHK 作为密钥来源,因为 AHK 是用户自己定义和写入的。AHK 只需要一次性烧录,不需要每次执行软件的时候写。不支持 AHK 的系列上则可以选择 DHUK⊕BHK。

DHUK⊕BHK 能够支持的另一个应用场景是,用户不仅希望硬件密钥有自己可控的部分数据参与,而且可控部分的数据可能随着软件的更新发生变化,比如某些时候如果需要让以前加密存储的数据失效,那么就可以在某个软件升级之后,软件写入新的值到 BHK,此后用 DHUK⊕BHK 加密数据时,就会采用新的密钥。

1.2.4 关于 SAES 密钥使用模式
1.2.4.1 Normal 模式

Normal 模式用于直接对数据进行加解密,例如选择密钥来源为 DHUK 时,输入明文数据到 DIN 寄存器,DOUT 寄存器则可以得到加密后的密文数据。

1.2.4.2 Key Wrap 模式

Key Wrap 模式可以用于安全存储和使用 AES 密钥。例如,如果希望存储一个 AES 密钥 Kclear,可以先用 Key Wrap 模式对明文密钥数据加密从而得到密文密钥,然后只需要存储这个密文密钥,而无需保留明文密钥在任何 Memory 中。后续可以直接导入存储的密文密钥进而恢复明文密钥,之后 SAES 硬件就可以用 Kclear进行数据的加解密操作,如图 5所示。

图5. SAES Key Wrap 模式

Key Wrap 模式下的加密操作用于加密某个 AES 密钥,例如对于需要加密的明文密钥Kclear,可以选择 DHUK 作为密钥来源,将明文密钥 Kclear作为数据输入给 DIN 寄存器,DOUT 寄存器将得到加密后的密文密钥 Kenc。这个密文密钥 Kenc可以存储在 NVM 中,方便后续的使用。

Key Wrap 模式解密操作用于导入之前 Wrap 的密文密钥 Kenc,也称为 Unwrap 操作。Unwrap 操作依旧选择相同的密钥(例如硬件 DHUK)作为密钥来源,Kenc作为数据输入给到 DIN,此时解密后的原始明文密钥 Kclear并不会出现在 DOUT,硬件会自动将其直接导入 SAES 密钥寄存器。Unwrap 操作完成后,已经导入的 AES 密钥 Kclear可以用于后续的数据加解密。

1.2.4.3 Key Share 模式

Key Share 模式同样可以用于实现 AES 密钥的安全存储与使用。类似地,在密钥导入阶段对原始明文密钥进行加密,此时加密操作选择 Key Share 模式,得到密文密钥数据,然后进行存储;在使用阶段首先对密文密钥进行解密,同样采用 Key Share 模式,这里不同于 Key Wrap 模式的是,Key Share 模式解密后的明文密钥不会被导入 SAES 的密钥寄存器,而是通过另一条私有总线自动导入 AES 模块,后续的数据加解密操作可以由 AES模块完成。Key Share 模式即能够在 AES 密钥存储和使用过程中很好地保护密钥的机密性,同时又可以使用 AES 模块更高的加解密性能。

过程如图 6 所示,如果希望存储一个 AES 密钥 Kclear,可以先用 SAES 的 Key Share 模式对 Kclear加密,得到密文密钥用于存储,后续需要使用密钥的时候,先用 Key Share模式对密文密钥解密并导入 AES 模块,然后 AES 模块就可以使用 Kclear进行数据的加解密。无论是存储数据还是加解密操作过程中,始终不会出现能够被软件获取到密钥数据明文的机会。

图6. SAES Key Share 模式
 

2 SAES 与 HUK 实现安全存储举例

2.1 数据安全存储

用例 1:数据安全存储

目标和期望达到的效果:

  • 加密存储机密数据,本机可以解密使用该数据。
  • 加密密钥一机一密,本机密文数据不能在另一台设备上解密,有防克隆效果。

实现方案:

  • 设备中的关键数据加密存储
  • 采用 SAES Normal 模式对数据加密和解密,选择 DHUK 或 DHUK⊕BHK 作为加密密钥。

由于 DHUK 每颗芯片都不一样,本机加密的数据只能在本机解密使用,同样的密文数据即使复制到另外一台设备上也无法解密,达到数据安全存储的期望目标,如图 7 所示。

图7. 数据安全存储示例

2.2 AES 密钥安全存储与使用

用例 2:AES 密钥的安全存储与使用

目标和期望达到的效果:

  • 用户需要存储自己的 AES 密钥,例如预置的共享密钥,用于数据通信中的加解密。
  • 本机应用可以使用存储的 AES 密钥进行加解密操作。
  • 密钥在存储和使用过程中始终保持密文形态,且使用过程中全程不暴露原始 AES 密钥明文,即软件、DMA、调试端口都无法获取 AES 密钥明文内容。
  • 加密存储使用的密钥为一机一密,存储的密文密钥不能在另一 MCU 上解密。

实现方案 1:

  • 密钥生成导入阶段:使用 SAES Key Wrap(密钥封装模式)加密原始密钥,并存储封装后的密文密钥数据,采用 DHUK 或 DHUK⊕BHK 作为密钥进行封装操作,设备上只存储密文密钥,导入后明文密钥可以销毁。
  • 密钥使用阶段:首先使用 SAES Key Wrap(密钥封装模式)进行解封装,也就是对密文密钥进行解密,密钥后的明文密钥只出现在 SAES 内部,且会自动导入 SAES密钥寄存器,此后,SAES 可以使用该密钥进行数据加解密。

实现方案 2:

  • 密钥生成导入阶段:使用 SAES Key Share(密钥共享模式)加密原始密钥,并存储加密后的密文密钥数据,采用 DHUK 或 DHUK⊕BHK 作为密钥进行封装操作,设备上只存储密文密钥,导入后明文密钥可以销毁。
  • 密钥使用阶段:首先使用 SAES Key Share(密钥共享模式)对密文密钥进行解密,解密后的明文密钥由 SAES 经过私有总线直接导入 AES 单元,此后,AES 模块可以使用该密钥进行数据加解密。

由于用户的 AES 密钥只以密文形式存储,且 DHUK 每颗芯片都不一样,本机存储的加密后的密钥数据只能在本机解密使用,从而达到 AES 密钥安全存储的目的。使用过程中,AES 密钥明文只出现在 SAES 或者 AES 模块内部,不会被软件获取,因而也达到了 AES密钥安全使用的效果。方案 1 的优点在于 SAES 本身有侧信道攻击防御能力,如果对密钥的保护有更高要求的时候可以采用方案 1;方案 2 中数据的加解密使用 AES 而非 SAES 单元,因此不具备侧信道攻击防御,但是也因此算法的执行效率更高,如果对加解密效率有更多要求的时候可以采用方案 2。

图8. AES 密钥安全存储与使用示例

2.3 非对称密钥安全存储

用例 3:非对称密钥的安全存储与使用

目标和期望达到的效果:

  • 以密文形式存储设备私钥,加密采用一机一密
  • 存储的密文密钥不能在另一 MCU 上解密,防克隆
  • 保护非对称密钥的访问和使用,只允许关键可信代码使用密钥进行签名验签等操作

实现方案:

  • 通过 SAES+HUK 对密钥进行加密(私钥加密存储,公钥部分增加完整性校验数据,可以选择加密或不加密),使用 SAES 普通模式对密钥数据加密和解密,密钥来源选择 DHUK 或 DHUK⊕BHK,实现一机一密安全存储,防克隆
  • 支持 TrustZone 架构的系列上,可以结合 TrustZone 安全隔离机制,密钥存储于Flash 安全区,存储的密钥只能由运行于安全区的可信代码操作,运算结果输出给非安全区的应用程序使用。

以图 9 所示为例,假设 MCU 采用 STM32U5/WBA/H5/N6 系列,支持 TrustZone架构。非对称密钥数据首先经过 SAES 加密,密钥可以选择 DHUK 或者 DHUK⊕BHK,加密后的密文密钥存储于 Flash 的安全区(或者在 STM32H5 上可以存储在 OBK 区,OBK区数据只能被安全代码访问)。需要使用密钥的时候,非安全侧代码调用安全侧提供的API,进行签名验签等操作,安全侧代码用 DHUK(或者 DHUK⊕BHK)对存储的密文密钥数据进行解密,解密后的明文密钥临时存放在安全侧的 SRAM 中,然后使用密钥做签名/验签运算,运算结束后清除 SRAM 中的临时明文密钥数据,并将运算结果(比如签名数据或者验签结果)通过 API 接口返回给非安全侧的应用程序。整个过程中 Flash 中存储的只有密文密钥,且密文密钥数据只能被本机解密,如果复制到其他设备上无法得到正确的解密结果,密钥使用过程中密钥明文只出现在 TrustZone 安全侧,只有安全侧的可信代码才能使用密钥数据进行运算,非安全侧代码、DMA 都无法访问到安全侧的任何数据,如果开启了调试端口保护功能,比如 STM32U5/WBA 上 RDP 级别设置到 0.5 或以上级别、STM32H5 Product State 设置到 TZ Closed 或者 Closed 级别,或者 STM32N6 处于默认的 BSEC Closed 状态且软件没有主动开启调试功能,则调试端口也无法访问到密钥数据,无论是明文还是密文密钥。

图9. 非对称密钥安全存储与使用示例

3 SAES/AES + HUK 使用常见问题

本小节将列举一些使用 SAES/AES+HUK 中的常见问题和解决方法。

3.1 SAES 初始化失败
3.1.1 问题现象

客户在 STM32U5 上使用 TF-M,但是没有使用 MCUBoot 的安全启动部分,Bootloader 采用自己的代码。TF-M 编译选项中开启了 Crypto 硬件加速,也就是使能了 TFM_HW_ACCEL_ENABLE 编译选项,从串口日志上看到 tfm_crypto_init 初始化失败,单步调试发现:1)单步调试时发现 tfm_crypto_init 执行时跳转不正确;2)单步调试到HAL_CRYP_Init 程序时,发现其初始化失败,位置如下:

3.1.2 问题分析

STM32U5 的 CubeFW 包中提供的 TF-M Example 包含两个部分,一个是基于 MCUBoot 的安全启动部分,一个是 TF-M 和 NS 应用,默认是从 MCUBoot 启动,再跳转 TF-M 工程。采用默认的启动流程时,问题不会出现,而单独执行 TF-M 工程时能够看到 CRYP 初始化失败的问题。

进一步研究发现时钟初始化的代码只在 MCUBoot 工程中执行一次,跳转 TF-M 工程后,TF-M 中不会再做时钟初始化。时钟初始化的代码中有两个重要的部分会影响到 CRYP/SEAS,即 HSI48 和 SHSI 时钟的使能。

原因是 STM32U5 的 SAES 算法内核由一个单独的 SHSI 驱动,这个时钟不使能,SAES 无法执行正常的算法运算,同时 SAES 的侧信道攻击防御实现需要用到 RNG 单元产生的随机数,使用 SAES 必须要同时使能 RNG 单元,RNG 默认依赖 HSI48 时钟源,因此使用 SAES 至少需要把 HSI48 和 SHSI 都使能

3.1.3 解决方法与结论

如果在 STM32U5 上单独使用 TF-M,或者使用客户自己的 bootloader 配合 TF-M,需要在 Platform 初始化代码中至少使能 HSI48 和 SHSI 两个时钟。如果用户的bootloader 工程没有做特别的时钟初始化,则一个简单的方法是把 MCUBoot 工程的Platform 初始化代码中的 clock 初始化函数复制添加到 TF-M 工程中(比如SetSysClock(void)函数),确保 HSI48 和 SHSI 都使能。

这里另外提示一下,在目前已经发布的几款带有 SAES 和 HUK 的 STM32 系列产品中,这个 SHSI 没有使能问题通常只会在使用 STM32U5 系列的时候遇到,因为其他的几个系列,例如 STM32H5,STM32WBA,STM32H7S,STM32N6 系列中,这些系列上SAES 的运算核不再由单独的 SHSI 驱动,内核和总线时钟使用相同的时钟源,只要 RCC中使能了 IP 的时钟就可以使用 SAES 进行加解密运算了。

3.2 STM32U5 从 stop 模式唤醒后 SAES 加解密结果异常
3.2.1 问题现象

客户 App 在使用 SAES 进行 GMAC 运算时,得到的结果全为 0。之前在做工厂版本测试时,并没有出现这个问题,后续使用用户版本测试时,发现这个问题。

3.2.2 问题分析

客户测试发现:

1)刚刚上电开机的时候是可以产生正确的 GMAC tag 的

2)用户版本 App 会经常进入低功耗模式,再唤醒,一旦进入低功耗模式,唤醒后再执行 SAES GMAC 操作就会出现运算结果全 0 的现象。

通过调查得知 Factory 版本总是在 run 模式,不会进低功耗,而 User 版 App 是开机几秒钟就会进入 stop 模式,唤醒后也会每隔一段时间进入 stop 模式。

根据现象猜测是因为进入 STOP 模式再唤醒之后有些时钟没有恢复。因为 STM32U5 SAES 除了普通的总线时钟,还需要单独的 SHSI 来驱动,因此尝试检查 RCC->CR 寄存器的 SHSIRDY 和 SHSION bit:

通过在线调试,在问题现象产生时读取 RCC->CR 寄存器 (0x56020C00)

- Stop 模式下读到都是 0 (正常)
- 唤醒后读到的结果是 33030535
- 刚刚上电正常情况下读到结果是 3303C535

由此可以判断进入 stop 模式之后唤醒的时候 SHSI 没有使能,这意味着从 stop 模式唤醒后 SAES 的内核驱动时钟没有使能,因此虽然软件可以操纵 SAES 寄存器,但是SAES 无法进行实际运算,导致运算结果输出都为 0。

3.2.3 解决方法和结论

从 stop 模式唤醒后,除了恢复相关外设时钟,在使能 SAES 时钟之前,增加 HSI48 和SHSI 时钟的恢复使能。

STM32U5 的 SAES 的正常工作,除了外设时钟本身以外,还需要 SHSI 来驱动其算法内核,另外 SAES 的侧信道攻击防御实现需要用到 RNG 单元产生的随机数,因此还需要使能 RNG 依赖的 HSI48 时钟,HSI48 和 SHSI 除了需要在正常的上电复位初始化中使能,如果系统会进入低功耗模式(例如 stop1, stop2),那么在唤醒之后也需要在相关code 中添加恢复这两个时钟的使能代码。如果在使用 SAES 之前没有使能 RNG 模块,也要增加 RNG 模块相关的使能代码。

3.3 使用硬件密钥进行多次 ECB/CBC 运算后出现解密结果异常
3.3.1 问题现象

客户用 SAES+DHUK Normal 模式加密了一段数据,密文数据存放在 Flash,软件代码中有一个函数负责对该段密文数据进行解密,上电复位后,这个函数可能会被调用多次。

程序初始化过程中 MX_SAES_AES_Init() 函数会对 CRYP 进行配置并调用 HAL driver的 CRYP 初始化函数。数据解密函数实现中直接调用 HAL_CRYP_Decrypt()函数对数据进行解密。类似如下代码:

测试中发现,第一次调用解密 API 函数时,可以得到正确的结果,解密后的数据与原始明文相符,而再次调用相同的 API 函数,得到的结果却发生了变化,不再是期望的明文数据,而是其他数据。

类似的现象发生在 SAES Key Share 模式。操作过程大致如下:

• HAL_CRYP_Init() 初始化 Instance 为 SAES,其中和 HUK 相关的配置包括

  • 密钥来源 KeySelect 选择硬件密钥 CRYP_KEYSEL_HW
  • 密钥模式 KeyMode 选择为 Key share 模式 CRYP_KEYMODE_SHARED

• 初始化完成后进行密钥解密和导入操作

  • 密文密钥通过 HAL_CRYPEx_DecryptSharedKey() 函数解密并导入 AES 模块。

• 接下来调用 HAL_CRYP_Init() 重新配置初始化 CRYP 模块

  • Instance 选择 AES
  • 密钥模式 KeyMode 选择为 Key share 模式 CRYP_KEYMODE_SHARED

• 其后使用 AES Instance 做数据加解密

  • 调用 HAL_CRYP_Decrypt() 对一段事先用已知密钥加密过的数据进行解密
  • 第一次调用可以得到预期的解密后的明文数据
  • 再次调用解密函数,无法得到正确结果
3.3.2 问题分析

这两个问题有相似性,都是使用硬件密钥时,ECB/CBC 模式解密操作只有第一次能得到正确解密结果,不做其他额外操作,直接再次调用解密函数将无法得到正确的解密结果。

进一步调查发现,如果在解密函数前每次都做一遍 CRYP 反初始化和再次初始化,即调用 HAL_CRYP_DeInit()和 HAL_CRYP_Init()函数重新初始化 SAES/AES 之后,解密操作总是能够得到正常结果。

阅读芯片的参考手册,可以看到 AES/SAES 模块对于几个加解密运算模式的描述

其中 Mode 1 是加密模式,Mode3 是解密模式,对于 ECB 和 CBC Chaining 模式,解密操作之前需要经过一个 Mode 2,也就是密钥准备操作,这里会有一个 key derivation 运算,用于从原始的加密 Key 得到解密 Key,Mode 2 操作之后,解密密钥准备完成,解密密钥数据会自动保存在密钥寄存器当中,之后才能使用 Mode 3 进行数据的解密运算。

在使用软件密钥的时候,HAL_CRYP_Decrypt()函数会完成密钥写入寄存器,设置Mode 2 准备解密密钥,再设置 Mode 3 进行数据解密的一系列操作。当使用硬件密钥的时候,HAL_CRYP_Decrypt()函数并不会进行密钥写入寄存器的动作,因为密钥来自硬件,通常会假设调用 HAL_CRYP_Decrypt()函数时,硬件密钥已经导入密钥寄存器,只需要做第二步 Mode 2 的解密密钥准备和第三步 Mode 3 的数据解密就可以了。因此,这种使用场景下,第一次调用 HAL_CRYP_Decrypt()函数可以得到正确的解密结果。

在第一次完成解密过程之后,密钥寄存器里面已经是经过 Mode 2 运算的解密密钥了,也就是 KeyDec,而非原始的加密密钥 KeyEnc,这时候再次调用 HAL_CRYP_Decrypt()函数做数据解密,依旧需要先经过密钥准备过程,这会导致密钥准备结束后,密钥寄存器的内容变成由 KeyDec 派生得到的密钥(KeyDec)Dec,而不是从原本的 KeyEnc派生得到的解密密钥 KeyDec,这会导致后续的解密实际上用了错误的密钥,如图 10 所示。

图10. 解密过程中密钥寄存器数据的变化

3.3.3 解决方法和结论

使用 SAES 硬件密钥做 ECB/CBC 解密操作,或者使用 AES 选择经过 SAES 用 Key share 模式导入的密钥进行 ECB/CBC 解密操作时,在调用 HAL_CRYP_Decrypt()函数之前,需要确保密钥寄存器里面已经加载了原始的加密密钥。也就是说在两个连续的 HAL_CRYP_Decrypt() 函数调用之间,需要重新加载密钥到密钥寄存器。由于硬件导入的密钥并不是通过软件写入,因此需要让 CRYP 再次加载原始的硬件密钥。为了达到这个目的,有两种解决方法。

方法一:在两次 HAL_CRYP_Decrypt()函数调用之间,进行 CRYP 反初始化和初始化,也就是调用 HAL_CRYP_DeInit()和 HAL_CRYP_Init()函数重新初始化 SAES 或者 AES(重新初始化 SAES 还是 AES 取决于解密数据使用 SAES 还是 AES 模块)。

方法二:在两次 HAL_CRYP_Decrypt() 函数调用之间,调用 HAL_CRYP_GetConfig() 和 HAL_CRYP_SetConfig(),重新写入 CRYP 的配置参数,示例代码如下:

提示:如果使用 Key wrap 模式,首先对密文密钥进行 unwrap,然后再用 unwrap 后的明文密钥进行 ECB/CBC 解密操作,也会出现类似的连续两次解密后输出数据异常问题,产生问题的原因是类似的,都和 decryption 所需要的密钥准备操作有关,但是 key wrap 模式时,类似的问题并不能够通过在两次解密之间重新初始化 CRYP 或者重新配置 CRYP 的方法解决。使用 unwrap 的 Key 作为 ECB/CBC模式解密密钥时,需要每次都先做unwrap,然后再做数据解密,也就是每次数据解密总是需要先调用HAL_CRYPEx_UnwrapKey()来获得解密密钥,然后再调用HAL_CRYP_Decrypt()做数据解密。

3.4 使用 SAES+HUK 加密数据时在不同芯片上得到的密文数据都一样
3.4.1 问题现象

客户尝试使用 DHUK 作为密钥来源,用 SAES 对一段数据进行加解密,因为 DHUK 是从硬件唯一密钥 HUK 派生而来,在不同芯片上应该产生不同的 DHUK,那么对相同的数据进行加解密应该得到不同的结果,然而用几个不同的芯片测试发现加解密的结果都相同,不符合唯一密钥的预期。

3.4.2 问题分析

STM32 的硬件设计上对 HUK 进行了保护,在调试完全开放的状态下(即 Open 状态)无法使用真正的 HUK,此时虽然也可以测试 SAES+DHUK 的数据加解密,但是在不同芯片上的 HUK 表现为一样的值,因此对同一段数据加解密的结果也相同。真正的 HUK只有在非 Open 状态下才可以使用。

这里说的 Open 状态和非 Open 状态,在不同的系列上可能指的是不同的芯片生命周期状态配置,比如在 Option Byte 支持 RDP 的系列上,Open 状态即为出厂默认的 RDP level 为 0 的状态,也就是调试端口没有任何保护的状态,非 Open 状态可以是 RDP level1 或者 level2,如果芯片支持 TrustZone,RDP level0.5 关闭安全侧调试的状态也是非 Open 状态。在 Option Byte 支持 Product State 的系列上,Open 状态即为出厂默认的 Product State=OPEN 的状态,其他状态,例如 Provisioning, Provisioned, Closed, TZ Closed 等均为非 Open 状态,详细的 Product State 状态说明请参考各个系列的参考手册。

表 3 列举了本文提及的几个系列中芯片生命周期状态配置以及对 HUK 的影响。

表3. 几个系列中 HUK 与芯片生命周期状态的关系

3.4.3 解决方法和结论

当芯片处在 Open 状态,真实 HUK 无法使用时,其表现为不同芯片的 DHUK 值相同。因此,如果想要测试 HUK 的硬件密钥唯一性,则需要根据不同系列的特性,将 RDP或者 Product State 设置到非 Open 状态后,再进行测试。

4 总结

前文中提到的几类常见问题的总结见 Error! Reference source not found.。

表4. SAES+HUK 使用中的常见问题和解决方法

5 小结

本文首先简要回顾了几个产品系列当中 SAES 和 HUK 的主要特性以及异同,然后通过几个用例介绍了基于 SAES 和 HUK 在不同应用场景中如何实现数据和密钥的安全存储与使用,最后列举了几个 SAES 和 HUK 使用中的常见问题以及解决方法。本文提及的主要是目前已经量产上市的几个支持 SAES 和 HUK 的系列,包括STM32U5,STM32H5,STM32WBA,STM32H7S,STM32N6,此外后续的一些新产品也会带有 SAES 和 HUK 特性,对相关的新产品来说,本文的内容也会有一定的参考价值。希望这篇文章能够对于希望在 STM32MCU 上使用 SAES 和 HUK 的开发者有所帮助。
 

http://www.lryc.cn/news/624678.html

相关文章:

  • Rust 教程之简介000
  • CSS:水平垂直居中
  • 【银河麒麟桌面系统】配置匿名文件夹与用户认证共享服务
  • 2025年秋招Java后端面试场景题+八股文题目
  • AI 推荐系统云端部署实战:基于亚马逊云科技免费资源的工程实现
  • 从财务整合到患者管理:德国医疗集团 Asklepios完成 SAP S/4HANA 全链条升级路径
  • CAN总线的安全性
  • Linux小白加油站,第三周周考
  • 世界模型之自动驾驶
  • 想找出版社出书?这样选就对了!
  • 《P1195 口袋的天空》
  • OVS:ovn是如何支持组播的?
  • GPT-5之后:当大模型更新不再是唯一焦点
  • 多硬盘构建lvm存储
  • GPT-5博士级AI使用教程及国内平替方案
  • 基于SpringBoot+Uniapp的互联网订餐小程序(协同过滤算法、Echarts图形化分析)
  • “Let it Crash“:分布式系统设计的涅槃重生哲学
  • 【笔记】位错的定义和分类
  • 【2025CVPR-目标检测方向】学习稳健且硬件自适应的对象检测器,以应对边缘设备的延迟攻击
  • Image-to-Music API 接入文档(图片生成音乐)
  • 综合布线系统的网络分线箱计量-文字查找精准定位
  • 区块链技术原理(16)-以太坊节点与客户端
  • 从0-1使用Fastmcp开发一个MCP服务,并部署到阿里云百炼 -持续更新中
  • 深入理解浏览器渲染机制:重排(Reflow)与重绘(Repaint)
  • 深入剖析以太坊虚拟机(EVM):区块链世界的计算引擎
  • 【低空安全】低空安全简介
  • OCR库pytesseract安装保姆级教程
  • 【LLM1】大型语言模型的基本生成机制
  • 特种行业许可证识别技术:通过图像处理、OCR和结构化提取,实现高效、准确的许可证核验与管理
  • 力扣32:最长有效括号