攻击硬件AES的差分故障分析
过去几个月,我一直在尝试从PlayStation Vita中提取硬件密钥。我写了一篇论文描述整个过程的技术细节,但我觉得也应该写一篇更随意的博客文章。可以将本文视为论文的配套读物,我会更多地阐述过程和遇到的死胡同,而不是仅仅呈现结果。我将尝试提供更直观的解释和背景信息,而不是追求技术精确性。
DFA
关于差分故障分析的实用介绍,请参阅这篇关于使用DFA攻击白盒软件AES的文章。作者给出了不过于学术化的良好解释,并最终提供了代码(我们将其用于攻击)。DFA的主要思想是:我们可以像对处理器那样对AES硬件进行故障攻击,但不是用它来控制代码执行,而是用它来使用正确密钥生成错误的AES加密。由于AES是一种脆弱的算法,微小的修改会导致其以意外方式泄露密钥信息,我们正是利用了这一点。
不幸的是,除了学术界,对AES DFA的兴趣不大。在Github上搜索只显示少量结果,总体上我们只找到两个严肃的AES DFA攻击实现。dfa-aes 实现了2009年的一篇论文,其中在第8轮注入一个精确故障并进行$2^{32}$暴力破解可以得到AES-128密钥。phoenixAES(来自上面链接文章的作者)实现了2003年的一篇论文,需要在第8轮注入两个独立的精确故障,无需暴力破解(尽管后来我们将描述一些放宽"精确故障"要求并将所需暴力破解增加到约$2^8$的修改)。从2002年到2016年,还有许多其他论文描述了假设故障发生在更早轮次、更多字节受影响或算法其他部分的攻击。然而,我们未能找到这些论文附带的源代码。最终,我们基于phoenixAES开展的工作,尽管它不是最先进的,但因为编写代码很无聊,而且文献中的大多数改进在实践中意义不大(一小时对比五分钟是很多时间,但如果只需要做一次,编写所有代码和调试的时间将抵消收益)。
抱怨 aside,主要工作在于完善我们的故障注入设置,以便在第8轮AES引擎运行期间注入精确(即最多损坏一个字节)故障。一旦设置完成,我们就可以将收集的样本输入phoenixAES(或dfa-aes),它应该就能正常工作。
DPA
在深入探讨我们如何设计DFA故障注入设置之前,值得先了解一下我们(失败的)对Vita进行DPA攻击的尝试,作为后续一些设计决策的背景。差分功耗分析是一种侧信道攻击,如果攻击者观察AES引擎在使用秘密密钥运行时的功耗,则可能泄露密钥。首先,她假设部分密钥的值。接下来,攻击者定义AES引擎的功耗模型,以预测如果加密随机输入且假设正确,将消耗多少功率。最后,她实际使用该输入运行引擎并测量实际功耗,以查看预测的接近程度。通过多次重复此过程并对密钥的不同部分进行操作,可以找到整个密钥。Chipwhisperer维基对差分功耗分析的工作原理有很好的介绍,更详细但仍易于理解。
要对目标进行DPA,您需要能够精确测量芯片中的电流。一种方法是应用法拉第定律:变化的磁场会感应出电压。您可以使用"磁探针"测量电流。Colin O’Flynn在黑帽大会上描述了如何构建自己的磁探针,我成功构建了一个并使其与ChipWhisperer示例目标配合工作。
不幸的是,环路的大小决定了测量的精确程度。5美元的DIY探针的环路尺寸几乎与整个芯片一样大,而AES引擎不到芯片总面积的1%,我们无法获得良好的信噪比。具有小环路尺寸的良好电流探针售价数千美元,这超出了预算。测量电流的另一种方法是应用欧姆定律:通过电阻的电流变化等效于电阻两端的电压变化。这需要更改电路,在电源和目标芯片之间引入一个小电阻。随着芯片消耗更多功率,它将从电源汲取更大电流,这会导致电阻两端的电压降更大。
为了利用分流电阻测量,我们首先需要切断PCB中从电源到目标芯片的走线。然后我们将目标芯片连接到我们的定制板,该板具有分流电阻以及用于测量探针的端口。我们使用外部电源为板供电(我们本可以使用Vita自己的电源,但连接外部电源更容易)。
定制设计的psvcw板具有分流电阻、滤波电容以及用于差分探针和CW故障注入器的端口。顶部还显示了探测通往目标芯片的eMMC信号的导线。我们使用它们既将有效负载刷写到eMMC,也触发电压故障以获取代码执行。
连接到psvcw的外部电源。 然而,即使使用分流电阻方法,我们也无法获得良好的SNR。外部噪声太多(可以通过足够的工作消除),但内部噪声也太多(更难消除)。我们观察到,在AES加密期间,SRAM读/写操作主导了功耗轨迹(幅度大许多数量级),因此很难找到轨迹与密钥之间的任何相关性。我们确定DPA在我们的设置中不可行,因为Vita的SoC是为低功耗而设计的。获得提高SNR所需的合适设备成本太高。
从0-50周期,触发GPIO信号切换开启。从250-350周期,AES操作发生。在600周期,触发GPIO切换关闭。全程的小凹陷可能是F00D处理器操作。 尽管名称相似,DPA和DFA完全不相似。DPA是(被动)侧信道攻击,而DFA是(主动)故障攻击。然而,尝试DPA的所有工作并没有白费。首先,我们获得了关于AES操作何时发生的宝贵信息。通过比较单次AES操作的轨迹与我们收集的其他轨迹(即没有AES操作或有多次AES操作),我们得出结论,AES操作发生在触发后约250-350周期功耗下降的地方。我们为插入分流电阻和降低测量中的SNR而进行的PCB修改也具有双重目的,即允许更精确的故障注入。这很重要,因为之前我们是以安全处理器为目标进行故障注入(为了获得代码执行),并且为了产生某种效果,进行多周期故障注入是可以的。然而,对于每个周期执行4次操作的AES引擎,我们需要能够引起尖锐的电压尖峰,而不会被设备的电源分配网络过滤掉。分流电阻对此有帮助。
PlayStation Vita的安全架构
为什么Vita,这款索尼商业上失败的产品,是一个如此有趣的攻击目标?那些关注我博客的人可以看到,在过去的几年里,Vita主导了我的兴趣。除了想向我最喜欢被忽视的游戏机表达一些爱意之外,我喜欢破解Vita的技术原因是因为它是一个极其独特的设备,实现了许多"正确"的安全功能。该设备于2012年发布,当时大多数Android手机没有启用地址随机化等基本漏洞缓解措施,而其直接竞争对手(3DS)存在重大的硬件和软件安全疏忽。
(我将尝试提供一些关于软件安全的背景知识,但如果您不感兴趣,请随时跳过。)操作系统完全专有,部分源自NetBSD,其他部分源自索尼PSP(本身也是专有的)。在大多数设备运行BSD、Linux或某种RTOS的世界中,作为逆向工程师,看到一个新的操作系统总是令人兴奋。专有并不意味着安全。虽然找到转储内核的"初始"漏洞极其困难(我们在2013年利用了少数NetBSD衍生组件之一),但隐藏代码不是安全,而是隐蔽。然而,值得称赞的是,整整一年没有人能够转储内核,即使在我们转储之后,又过了三年也没有其他人做到(直到我们发布了越狱)。内核本身具有所有针对缓冲区溢出攻击的标准缓解措施和防止地址泄露的保护措施。它还具有一些当时非标准的缓解措施,如SMAP和系统调用防火墙。Vita也使用ARM TrustZone,但在Android手机会将其所有秘密存储在TrustZone中的时候,Vita仅使用TrustZone作为与F00D安全处理器接口的缓冲区。只有TrustZone可以直接与F00D处理器通信,但TrustZone本身没有秘密,事后看来这是一个好主意。
Bigmac
如果我们想了解内容(游戏、数据、固件、更新等)如何被解密,我们必须查看F00D处理器,这是一个处理所有加密和安全关键任务的卫星处理器。F00D运行在基本上未文档化的架构上,但我们及时成功破解了它。然而,即使破解F00D也不足以完全"拥有"系统。F00D代码中有许多加密密钥,但最重要的密钥,包括解密引导加载程序的密钥,隐藏在硅片中,只能被我们称为Bigmac的硬件AES引擎访问。有250个这样的密钥槽。其中30个密钥被称为"元"或"主"密钥,因为Bigmac只允许使用它们将数据加密到另一个密钥槽(即派生密钥)。不可能直接使用主密钥加密数据并查看密文。
大多数密钥槽(包括所有主密钥)在引导加载程序执行之前被锁定。这意味着只有引导ROM被允许在Bigmac中使用它们。因此,总结路线图,在到达这一点之前我们必须已经破解了:WebKit以获得初始执行,ARM内核,ARM TrustZone,F00D内核和F00D引导ROM。从零开始,我们花了六年时间到达这一点,除了F00D引导ROM外,都是通过软件漏洞完成的。(我们将所有知识转储到了一个社区维护的维基中。)理性的观察者可能想知道所有这些的意义何在。出于所有实际目的,破解ARM内核足以越狱系统、运行自制程序和模组,以及(不幸的是)盗版游戏。然而,理性的观察者可能在CTF活动中毫无乐趣。六年前,我为自己设定了一个任意目标:获取引导加载程序的解密密钥。想法是,如果我们可以解密第一段可加载代码,那么索尼就无法在未来的更新中隐藏代码。后来,这个"根解密"密钥获得了名称:槽0x208(一个元密钥)。这篇文章是关于夺取那最后一面旗帜,这六年旅程的最后一段。
故障注入和DFA
之前,我谈到过如何使用电压故障注入在F00D安全处理器上获得启动时代码执行。DFA与之有何关系?因为大多数密钥槽在引导ROM退出到引导加载程序之前被锁定,我们需要在接管引导ROM后执行DFA攻击。为此,我们必须使用之前找到的相同故障注入参数对F00D重复电压故障注入攻击。之前,我们执行的有效负载只是转储引导ROM,但现在已被RPC替换,以便我们可以通过ChipWhisperer的串行接口从PC控制Bigmac。一旦此RPC有效负载运行,我们可以使用不同的触发信号和参数执行第二次故障注入,以便在Bigmac AES中引起故障。主要任务是找到这第二组参数。一旦拥有它们,我们就可以开始收集错误的密文,方法是使用RPC发送Bigmac命令,触发故障,下载错误的密文,并重复。有了足够的错误密文,最后任务是进行DFA攻击以提取密钥。
psvemmc板将所有所需信号从Vita的PCB收集到一个地方。它包括用于eMMC触发(通往板背面)、时钟(替换Vita自己的时钟合成器芯片)、UART、电源、复位和GPIO触发(重新路由LED信号)的导线。它还有一个开关以启用eMMC刷写模式,该模式使用USB2244和电平转换器通过USB支持1.8V eMMC刷写。
一切连接并工作。
分析错误密文
为了将故障注入AES操作,我们使用RPC切换GPIO引脚并立即启动Bigmac。GPIO切换设置一个参考点并作为故障注入器的触发信号。我们需要在触发后等待一定数量的周期再执行第二次故障注入。从上面的功耗轨迹我们知道,在触发后250到350周期之间发生AES加密。当我们在偏移240-280尝试故障注入时,我们得到错误的输出密文。然而,我们不知道哪一轮受影响或状态中有多少字节被破坏。回想一下,要使用phoenixAES,我们需要两个错误的密文,每个在第8轮有一个字节被破坏,并且两个错误的密文不相同。
为了弄清楚周期偏移与哪个AES轮被故障之间的关系,我们可以将已知密钥传递给Bigmac并尝试加密已知明文。然后我们使用已知密钥"解密"错误的密文。在解密的每一步,我们可以将状态矩阵与解密正确密文的相同步骤的状态矩阵进行差异比较。我们可以假设状态中翻转位数最少的步骤是我们成功故障的步骤。为什么?因为AES通过设计确保了一种称为扩散的特性。这意味着输入中的单个位翻转平均应导致输出中一半位翻转。AES中的每一步都试图将状态中的小变化传播到尽可能多的位置。例如,假设我们在第5轮的MixColumns之后成功注入了故障,使得字节0中的单个位翻转,将0xAA更改为0xAB。在第6轮的SubBytes中,字节0被传递到S-Box,其中输入0xAA产生输出0xAC,但输入0xAB产生输出0x62。注意我们现在有5个位翻转。继续到第6轮的MixColumns,我们看到每列被打乱,这意味着现在有4个字节不同。然后在第7轮的ShiftRows中,这4个字节中的每一个被重新定位到不同的列,另一个MixColumns将进一步打乱每一列(现在所有16个字节都不同),如此再进行3轮。很容易看出,一轮状态中的微小变化会导致随着我们进行更多轮次,状态发生巨大变化。
利用这一点,我们可以在每个偏移处收集许多样本错误密文,并查看每个偏移主要影响哪一轮。下面的视频显示了这一过程的工作情况:我们更改故障注入偏移并触发故障,然后立即分析故障以查看哪一轮受影响以及状态中的哪些位被翻转。
观看DFA分析脚本 + 微调故障注入 - Vita Hacking from YifanLu on www.twitch.tv
此外,我们还发现,无论偏移如何,我们的大多数故障只影响一或两个位。这比phoenixAES要求的(单个字节损坏)更好。
提取密钥
使用正确的偏移,我们可以在第8轮获得故障。以高概率,我们获得1-2位翻转,并且它适用于phoenixAES的要求。然而,如果我们不幸收集了两个具有> 1字节损坏的错误密文怎么办?我们确实遇到了这个问题(这并不完全基于运气)。这里的"最佳"解决方案是更改故障模型。我们使用的是Piret在2003年首次提出并在phoenixAES中实现的模型。然而,后来的模型允许最多12字节的损坏(尽管有一些限制)。由于我们懒惰且不想编写大量代码,我们可以做一些次优的事情。
笨拙的DFA
这里的关键见解是,如果我们传入两个"不符合模型"(损坏超过1字节)的错误密文,它将返回无解。那么,我们何不尝试每一个错误密文的组合?在找到有效对之前,我们必须尝试多少次?
假设以概率$p=0.25$,我们获得一个1字节错误密文(上面的直方图显示此估计是保守的)。我们预期收集的密文数量$X$,直到获得一个这样的密文,遵循几何分布,且$E[X]=1/p$。根据期望的线性性质,两个这样的密文将需要$m=2E[X]=2/p=8$个样本。(实际上每次试验并非独立,但这给了我们一个粗略的概念。)
如果我们有$m$个样本,那么我们的"暴力破解"方法将需要$(m^2)=O(m^2)$次尝试来找到密钥。实际上,对于$m \lessapprox 2^{16}$,这种笨拙的暴力破解解决方案优于dfa-aes实现的2009年结果(参见开头关于DFA的部分),该结果只需要第8轮的一个故障但需要$2^{32}$暴力破解。
稍微更笨拙的DFA
如果我们能假设故障注入翻转的位是独立的,那就太好了。然而,实际上情况并非如此,因为"哪个位被破坏"取决于晶体管的物理布局以及工艺变化和处理的数据。对于约$20%$的槽,我们无法获得在第8轮仅有一个字节损坏的错误密文。由于我们已经在对输入phoenixAES的两个错误密文进行暴力破解,我们一时兴起,还决定用每个错误密文替换正确的密文输入(尝试次数为$(m^3)=O(m^3)$)。像魔术一样,这奏效了,我们得到了剩余的密钥!现在,根据您的个性,您可以将此视为上帝的礼物,或者您可以彻夜思考它为什么有效。证明在论文中给出,但有点技术性且不太有趣。简短的版本是,由于我们正在进行差分分析,如果相同的位在"正确"密文以及两个损坏密文中都被翻转,一切仍然有效。这意味着翻转位缺乏独立性实际上帮助了我们。
不过有一个缺点。我们失去了如果找到解则它正确的假设。对于少数槽,我们意外地破坏了两轮的状态,最终得到了稍微错误的密钥。然而,一旦我们识别出此错误,我们能够通过假设密钥最多有4位错误(回想故障破坏的位数的分布)然后暴力破解$256^4$种密钥可能被破坏的方式来找回正确的密钥。
扩展到AES-256
到目前为止,我们只提到了攻击AES-128密钥。然而,将其扩展到AES-256并不太困难。我们不是攻击第8轮,而是攻击第12轮以获得相同的结果。但这只得到一半的密钥。要获得另一半,我们需要应用找到的轮密钥来反转一轮AES。然后我们以相同方式攻击第11轮,结合两个轮密钥,我们可以得到完整密钥。
完整设置:psvemmc通过USB供电并通过20针连接器连接到ChipWhisperer。CW故障注入端口连接到粘在板底部的psvcw,其中包含分流电阻。CW测量端口连接到CW105差分探针,该探针也插入psvcw板。CW105探针的电源是来自eBay的5美元DC-DC转换器,源是通过USB供电的RPI Zero。红蓝线将外部1.1V电源连接到psvcw。最后,电池和USB多连接器为Vita本身供电。盒子不仅仅是广告;它以轻微角度固定CW,这样扭矩不会将psvemmc板上的胶水撕开。这种创新解决方案是几周对电线不断脱落的沮丧的结果。
主密钥
到目前为止,描述的一切都适用于非主密钥。回想前面我们说过主密钥不能直接用于加密内容。相反,过程涉及使用Bigmac将一些明文加密到另一个密钥槽,而从密钥槽也无法读出。当然,解决此问题的一种方法是执行两级DFA攻击:一次故障填充从密钥槽,然后使用从密钥槽进行$m$次故障以获得主密钥槽的错误密文。然而,我们没有走这条路,因为我们已经知道Bigmac中存在一个硬件漏洞可以暴露从密钥。
Davee写了一篇很好的文章关于此漏洞的工作原理。简而言之,因为Bigmac在成功加密后不清除内部状态,如果您执行大小< 16字节(AES的块大小)的第二次加密,那么它从该内部状态"借用"剩余字节(恰好与从密钥相同,因为它是最后的加密操作)。利用这一事实,我们可以通过四次$2^{32}$尝试暴力破解剩余字节来恢复单个从密钥。(您可能注意到这里出现了一个主题:如果某件事不工作,就暴力破解它。)
对于每个主密钥槽,我们收集约$m=100$个这些从密钥"部分"的样本(为了安全)。然后我们运行Davee的工具来"破解"这些部分并恢复从密钥。这个从密钥是损坏的密文。然后我们进行上述相同的DFA攻击,我们也可以恢复主密钥。
对于部分破解,我们启动了一个AWS c5.18xlarge spot实例(具有72个AES-NI启用核心),可以在约15秒内破解一个部分(我们见过的最长仍然不到一分钟)。
AWS EC2核心利用率超过几个小时。
结论
我们恢复了所有30个主密钥,包括槽0x208密钥。
我们还恢复了240个非主密钥中的238个。最后两个是用于全盘加密的AES XEX密钥,并在我们可以执行RPC有效负载(从eMMC加载)之前被锁定。获取它们需要额外的工作,我们发现这没有用,因为密钥是设备唯一的。
成本
这样的攻击并不像人们想象的那么昂贵。我们是业余爱好者,只在半年内的空闲时间进行这项工作。我们没有获得任何资金或进入任何专业实验室。整个实验的总成本,从设备到板卡到AWS EC2,很容易低于1000美元。大部分成本是Rigol示波器(用于调试)(400美元)和ChipWhisperer Lite(300美元)。在一个软件攻击越来越难执行,公司用硬件安全保护越来越多软件的世界里,硬件没有得到同样好的保护似乎是一个巨大的疏忽。
剩余成本主要由9块Vita主板的死亡所主导。以下是它们的讣告:一块提供了eMMC的引脚定义,两块导致认识到3.3V eMMC会损坏SoC,一块教导了保持烙铁不过热的重要性,两块带来了探测时的谨慎,因为将相邻的1.1V核心短接到1.8V IO是不允许的,一块因回流焊的热膨胀导致切割走线上的内部金属变形并短路,两块死于神秘原因。(感谢所有为此实验捐赠备用Vita板的人。)
代码
与往常一样,本文中引用的所有工具都是公开和开源的。请查看论文以获取有关设置和实现的更多细节。
- 我们的ChipWhisperer分支包含故障注入Vita目标所需的所有修改。
f00dsimpleserial包括RPC有效负载、运行它的ChipWhisperer脚本、故障注入Bigmac和收集密文的ChipWhisperer脚本、分析脚本以及基于phoenixAES的DFA工具。f00d-partial-buster暴力破解部分以获取从密钥。psvemmc和psvcw用于与ChipWhisperer接口的目标板。