实战SM4故障攻击:从理论到硬件实现

本文详细介绍了针对SM4分组密码的实用故障攻击方法,包括攻击原理、工具实现及在真实硬件上的应用。通过故障注入技术,成功恢复SM4密钥,展示了低成本攻击的可行性。

实战故障攻击对抗SM4

在Hardwear.io 2022会议上,Nicolas和我展示了针对SM4分组密码的硬件攻击。本文将详细介绍我们展示的故障攻击及发布的工具。

我们开始研究这一算法时,发现了WCH的CH569w SoC,其包含执行SM4的硬件加速器。随后我们了解到SM4是中国的事实标准,且部署越来越广泛。例如,ARM自ARMv8.4引入两条指令sm4e和sm4ekey以加速SM4计算。RISC-V也集成两条指令实现类似加速。

根据IETF草案,SM4是一种分组密码,采用128位密钥,对128位明文块执行32轮加密。与AES类似,它包含密钥调度,生成36个轮密钥,每个32位。前四个轮密钥是密钥与称为家族密钥的常量FKs异或的结果。随后每个轮密钥根据以下图表生成,其中CKs是标准定义的常量。

作为 notation,所有大写字母表示32位字,小写字母表示字节。在一轮中,仅生成一个新轮密钥,其他三个简单右移。因此,从四个连续轮密钥,算法是可逆的。

最后32个轮密钥用于加密或解密块的32轮中。SM4的一轮与密钥调度非常相似。一轮通过以下操作将128位状态转换为另一个状态:

与密钥调度的差异之一是T函数,其与密钥调度的T’略有不同。T函数根据以下图表工作:

其中L是线性变换,具有32位输入和32位输出,用于字内扩散。S是S盒,具有8位输入和8位输出。与AES类似,Sbox基于逆和仿射变换。

文献中的第一个故障攻击由Zhang和Wu于2006年发布。论文用中文撰写,但攻击是所有后续故障攻击的基础,一些英文论文对其进行了良好描述。该故障攻击的思想是在最后一轮输入的第二个、第三个或第四个字节中引入随机字节故障。因此,故障直接在密文中可观察,因为这些字在一轮中简单移位。T函数输入也被破坏,其输出在密文中可观察。例如,最后一轮第三个字的故障导致以下结果:

攻击的思想是通过应用从随机字节故障𝛼引入的差分分析来恢复最后一轮密钥的字节k。它从编写Sbox输出差分的公式开始:

为简化,所有Sbox输入被变量x替换。然后攻击通过应用L函数的逆向后进行,直到T的输出:

我们获得一个仅有一个非零字节的字。它匹配注入字节故障的位置。现在问题是找到未知字节x,使得:

为解决此问题,攻击构建静态表IN,使得:

该表对SM4 SBox唯一,包含满足先前方程的x集合。构建该表将显示每个条目平均仅有两个不同x。攻击进行如下:

从故障密文计算𝛼和𝛽 查看IN[𝛼][𝛽]并推导x的候选列表 从表中存储的x异或所有输入字节以恢复轮密钥字节候选k 保留轮密钥字节候选列表 然后直到所有候选列表的交集没有唯一元素,重复先前步骤

平均而言,仅需两个故障密文即可恢复一个轮密钥字节。因此,需要八个故障密文恢复完整轮密钥。一旦轮密钥恢复,我们可以反转最后一轮并对前一轮应用相同攻击,依此类推。一旦恢复四个轮密钥,我们可以反转密钥调度并恢复秘密密钥。平均需要总共32个不同故障。关于SM4故障攻击的论文通常有实验部分展示其攻击性能,但从未发布软件以重现结果。然而,我们找到了先前故障攻击的实现,并将其作为起点。

该攻击具有实用性,因为故障密文与正确密文仅相差五个字节。例如,我们模拟了最后一轮的故障,如果将它们与正确密文(先前列表中的第一个值)异或,我们有以下模式:

在大量随机外观密文中排序故障非常方便。我们在称为phoenixSM4的工具中实现了此攻击,该工具集成在side channel marvels的伟大存储库中。该工具可以轻松安装为Python包:

1
pip install phoenixSM4

对先前故障应用此攻击将允许逐字节恢复最后一轮密钥。

然后我们尝试在更有趣的情况下应用此攻击。我们使用称为Glitchoz0r 3000的工具在ARM二进制文件中注入故障,使用C实现的SM4。我们模拟跳过指令的故障,并收集所有 resulting 故障密文。

但当我们排序故障以查找相同模式时,无法找到它。然而,我们有其他有趣模式:

但我们无法直接应用故障攻击。我们回顾学术文献,并发现了Li和Gu于2007年发布的扩展故障攻击。攻击的主要思想是在早一轮注入相同故障。在此场景中,故障将传播到下一轮的完整字,并影响SBox输入的所有字节。

由于输入和最后一轮输出仍然可用,我们可以应用先前攻击,但这次并行处理所有轮密钥字节。一个字仍然不受故障影响,它允许根据此模式过滤故障密文。实际上,论文甚至进一步分析早一轮发生的故障,在此情况下,仅两个故障允许连续恢复两个完整轮密钥。

我们也实现了此攻击,并发现可以通过在每次故障之间保留密钥字节候选来将此攻击与先前攻击结合。它允许利用最后三轮发生的故障。一旦轮密钥恢复,我们的工具将反转轮并继续攻击,直到恢复四个轮密钥。我们还注意到扩展攻击不适用于第二轮,因为输出不直接可观察。对于硬件中发生的某些故障,T的计算直接故障,但输入寄存器值未故障。因此,对于此类故障,攻击仍然适用,并将故障攻击的适用性扩展到此字。

因此,我们在先前收集的故障上测试了我们的工具:

我们可以看到,对于某些步骤,轮密钥完全恢复,而不是像先前那样逐字节。然后从四个轮密钥,可以通过我们在Stark中实现的反向密钥调度回到秘密密钥:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ ./sm4_keyschedule C337204D D1C1C4AF 19237F5D AB6618FE 32
Key: 01234567 89ABCDEF 12345678 9ABCDEF0
K00: A292FFA1 DF01FEBF 7549C7EF 28CCFC2C
K04: F12186F9 41662B61 47E428DB 2CE3DB57
K08: 75E66F59 143D5E48 60FDA097 34E52BB1
K12: 8F014121 9DB355C8 5E7B4216 9AEFF625
K16: 6B384C62 1B0BD5D1 6C16B475 EA885F28
K20: 6B0F7ED5 60D23EC0 328B69B7 FA3386F7
K24: 7814E4E0 37128B07 BB1231C6 CCDA92E7
K28: 2480AF60 14024020 92E84954 85499C75
K32: C337204D D1C1C4AF 19237F5D AB6618FE

这完全恢复了秘密密钥。

我们在真实硬件生成的故障上测试了我们的工具。我们使用NewAE的ChipShouter进行EM故障注入,使用400V脉冲和150ns持续时间,以及库存顺时针线圈。

经过几天扫描,我们获得了一些有趣的故障密文,用于设置为“A”十六次的明文。我们在它们上使用了我们的工具:

这表明该SoC的SM4实现易受低成本故障注入攻击。我们的工具作为开源发布,我们鼓励您测试它,甚至纠正或改进它。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计