关注了就能看到更多这么棒的文章哦~
Constant-time instructions and processor optimizations
By Jonathan Corbet
February 3, 2023
DeepL assisted translation
https://lwn.net/Articles/921511/
在对加密代码进行的所有攻击中,最隐蔽的攻击方式可能就是时序攻击(timing attack)了。一个看起来代码写得很正确的算法,甚至都可能带有 formal proof 来证明其正确性,还是可能会因为一些所依赖的数据的时间差异而导致信息泄露。Arm 公司和英特尔公司都引入了旨在帮助防御时序攻击的模式(mode),但这些模式在内核中应该得到多么深入的采用,目前仍在讨论之中。
Timing attacks
时序攻击,是通过观察完成一个操作需要多少时间来实现的;如果这个时间会根据被操作的数据而产生变化,就可以被利用来重建出这个数据了。讲一个简单的例子,有一个密码检查功能,它只是将一个提供的字符串与存储在一个安全的位置的密码进行比较。一个合乎逻辑的实现就是从头开始逐个比较字符,一旦发现一个不正确的字符,就返回一个失败状态。该算法可以直观地这么来写:
nchars = max(strlen(attempt), strlen(password));
for (i = 0; i < nchars; i++)
if (attempt[i] != password[i])
return false;
return true;因此,这个检查所花费的时间就是字符串开头的正确字符数量的一个函数。攻击者可以利用这些信息来重建出密码,每次可以确定出一位数字是对的。现实世界里的时序攻击,可以用来比如说提取密码密钥,这种方式已经被多次演示过了。
相应地,安全开发人员已经学会了在他们的代码中避免依赖数据的时序(data-dependent timing)变化。例如,在上面的例子中,无论在哪里发现第一个错误字符,整个密码串都会要完成比较。但是,如果这段代码运行的 CPU 有自己的时序特征,那么所有这些很仔细设计的方案都会被破坏。LWN 读者们肯定会感到震惊,因为事实上,CPU 确实表现出了这样的行为。
CPU 厂商并非没有意识到这个问题或其重要性。但他们也不是不知道一些引入时序差异的优化对某些基准测试结果有多大好处。安全性和性能这两个目标之间经常是互相伤害的,这里也是一样,CPU 供应商采取了通常的方法:让用户弄清楚他们想牺牲哪一个,从而获得另一个。
Constant-time processor modes
因此,Arm 和英特尔都引入了一些模式(mode),保证一些指令无论操作数是什么,都会花费恒定时间完成。在 Arm 的情况下,这种模式被称为数据独立计时(DIT,data independent timing);英特尔将自己的类似模式称为数据操作数独立计时(DOIT,Data Operand Independent Timing)模式,通常称为 DOITM。这两种模式都未默认启用。
早在 2022 年 8 月,Eric Biggers 询问这些模式是否应该由内核来启用。讨论结果最终导致 Ard Biesheuvel 的一个 patch 被合并,从而为 arm64 架构启用 DIT,但只在内核态运行时才会启用。默认情况下,用户空间的 DIT 仍然是关闭的,但在该架构上启用它并不需要特权(开销也很小便宜),所以用户空间的开发者可以在他们觉得有需要的时候就简单地启用就好。这个功能将是 6.2 内核版本的一部分;截至本文写作时,它还没有被移植回任何一个稳定版 kernel。
x86 的情况不太清楚。DOITM 是由一个特定类型的寄存器(MSR)控制的,不能由用户空间改变。在 8 月的讨论结束之后,Biggers 试图在 10 月重新开始继续讨论。他在一月份又回来了,再次询问 DOITM 是否应该在 x86 中默认启用,他主张应该这样做:
加密算法需要恒定的指令执行时间,以防止基于执行时间来复原出加密密钥的这类旁路攻击(side-channel attacks)。因此,如果不补上这个 CPU 漏洞,基本上不可能在最新的英特尔 CPU 上安全地进行密钥认证。
Dave Hansen 对这个想法不太热心,尽管他的结论是 "一般来说,这样做是正确的"。他指出,英特尔文档中的用语指出,DOITM 只对那些特别考虑到时序差异而编写的代码有附加价值:
从英特尔的话语中翻译过来。英特尔认为 DOITM 纯粹是一种让 CPU 运行得更慢的方法,如果你还没有专门写代码来缓解时序方面的旁路攻击的话。所有的损失并不会带来什么收获。
而内核整体并未采用这个原则来写。
他说,DOITM 只对用户空间中少量精心编写的加密代码有用,而对其他一切代码都会造成性能损失。他还指出,英特尔明确警告说,DOITM 的性能影响可能 "在未来的处理器上显著提高"。“Ice Lake”这一代处理器是第一个可以看到 DOITM 的效果的处理器;在之前几代的处理其上,恒定时间操作显然已经是默认标准行为了。
Biesheuvel 认为,DOITM 的价值超越了用户空间的加密库,它甚至跟内核更加相关:
但是对于特权执行来说,这应该是另一种情况:在内核中,data dependent timing 的优化范围非常狭窄,因为它处理的任何数据都必须被默认为是保密的(相对于用户空间),内核里的数据依赖的优化是确保安全的,因此很难找出 CPU 密集型的工作并相应地进行提速。
Biggers 质疑 Hansen 对性能方面的关注,他说,从数据依赖优化中受益最多的内核操作几乎肯定是最需要保护的,因为它们是会显示出最强的时间差异。他总结说:
我认为这里真正的结论是,英特尔显然试图引入的优化是一个坏主意,根本不安全。在它们存在的范围内,它们应该是一个 opt-in 方式可选加入的东西,而不是 out-opt 也就是可选移除的东西。CPU 的做法是错误的,但 Linux 可以将其扭转过来,把事情做对。
Hansen 回答说,社区已经 "研究了这些问题中每一个问题的治疗方法与要解决的问题比起来有多糟糕",他提到了其他类型的一些硬件漏洞。他说,DOITM 是不同的,因为随着时间的推移,它看起来可能会变得更糟,而不是更好;这使得它很难在内核中提出一个合理的 policy。他后来补充说,经过英特尔内部的讨论,他觉得内核社区不应该首先启用 DOITM:"我只想说,DOITM 不是被设计成一直打开的。如果软件一直把它打开,它就不能达成它的设计目的了。他说,这样做会使系统失去未来的 "各种各样的新优化"。
这次也没有得出结论,至少目前还没有。到目前为止,没有人发布任何测试数据来展示 DOITM 的性能影响是什么样的。假设开销不是很高,但如果 DOITM 最终没有在内核中被默认启用,并且在用户空间可以选择启用,那将是一个令人惊讶的结果。毕竟,"Insecure by default" 很难给用户留下什么好印象。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

文章探讨了时序攻击的威胁,即使正确编码的加密算法也可能因数据依赖时间差异导致信息泄露。Arm和Intel引入了constant-time模式以防御此类攻击,但内核中是否应默认启用这些模式尚在讨论。在x86平台上,由于DOITM模式不能由用户空间更改,性能与安全性之间的权衡成为焦点。
808

被折叠的 条评论
为什么被折叠?



