LWN:RDSEED 引入的危机!

关注了就能看到更多这么棒的文章哦~

Pitchforks for RDSEED

By Jonathan Corbet
February 8, 2024
Gemini translation
https://lwn.net/Articles/961121/

随机数(或者说是不可预测的数字序列)的生成是很多安全技术的关键。因此,这些年来,CPU 要能够提供随机数据这一个特性,引起了很多关注。一个合适的基于硬件的随机数生成器可以解决某些系统难以获得随机性的问题,但前提是相信制造商没有以某种方式损害该生成器。然而,最近的讨论揭示出另一个问题:如果一个硬件随机数生成器能够被简单地消耗殆尽,会发生什么?

作为背景,有必要了解 x86 系统上提供的两个相关指令:

  • RDSEED 是一个真正随机数生成器;它从环境中收集熵,并将随机 bit 序列存储到 CPU 寄存器中。它主要用于伪随机数生成器的种子或需要最高质量随机性的其他应用程序。

  • RDRAND 从内置于硬件中的确定性随机数生成器获取随机的数字序列,并将该模式存储到寄存器中。 RDRAND 所使用的生成器会定期从 RDSEED 所使用的来源重新获取种子。

RDRAND 被推荐用于大多数用途;它更快,并且可以显著增加可用于系统的熵量。在内核中, RDSEED 用于给内核的随机数生成器提供种子,但很少用在其他用途。值得注意的一点是,这两个指令都不是特权指令;用户空间代码同样可以使用。另一个重要的事实是,如果可用熵不足,这两个指令都可能会失败。(有关这些指令工作原理的更多详细信息,请参见 本页)。

在 x86 架构上,内核具有两个函数,rdseed_long() 和 rdrand_long(),它们会使用上述指令。Kirill Shutemov 最近观察到,虽然在 RDRAND 失败时 rdrand_long() 会重试十次,但 rdseed_long() 却会在相同的情况下立即放弃。他发布了一个 补丁,在 rdseed_long() 中添加了一个重试循环,另一个补丁 则是在即使十次尝试都没能获得成功结果时发出警告。这就是因出了后续的讨论。

它们能失败吗(我们关心它们失败的情况吗)?

最初,对于这些指令是否会失败,人们有点不确定。 RDSEED 能够以很高的速率产生熵,而 RDRAND 大大提高了该熵,所以似乎不太可能耗尽。内核随机数生成器的维护者 Jason Donenfeld 担心,如果 CPU 的随机数生成器可以被驱动到出现失败,就可能会导致拒绝服务问题。然而,Dave Hansen 认为这种担忧是多余的;他 权威地发言:

尽管 SDM 允许这样做,但我们(软件)需要在设计上保证 RDRAND/RDSEED 故障极其罕见。如果并非如此,我们将拿起我们可以信赖的火把和干草叉,追究那些制造了有问题的硬件的人的责任。

重复一下我说的:
常规 RDRAND/RDSEED 故障只会在损坏的硬件上发生

然而,似乎现在就可能为那些干草叉找到用武之地了。Donenfeld 编写了一个小程序 来通过反复执行 RDRAND 和 RDSEED 指令对硬件进行压力测试;他观察到,在单线程测试中, RDSEED 几乎有 30% 的时间会失败。然而,硬件随机数生成器由所有处理器共享这同一个 CPU,所以多线程测试应该会出现更糟糕的结果。实际上,Daniel P. Berrangé 报告 说,在多线程测试中, RDSEED 只有 3% 的时间成功了。没有人能够证明 RDRAND 会失败,但是正如 Berrangé 稍后在讨论中指出的那样,随着线程数量的增加,这种情况可能会发生变化。Elena Reshetova 也 承认,可能会有办法迫使 RDRAND 失败。

显然已经很明确了,通过锲而不舍的努力,可以使 RDSEED 失败,而 RDRAND 的可靠性也不能得到保证。下一个合乎逻辑的问题是:这有多大的影响?对于大多数用例来说,几乎没有什么值得担忧的。如果硬件随机数生成器偶尔失败,内核随机数生成器将继续产生不可预测的输出,即使在没有其他熵源的情况下也是如此。正如 Ted Ts'o 指出的那样,内核使用它能够找到的任何可能的其他熵源(例如中断时间的变化),并且即使 RDRAND 完全被破坏了,内核的方案也应该健壮了。由于大多数应用程序从内核获取随机数据,即使 RDRAND 不可靠也不应该成为问题。

但是,有一个值得注意的例外:众所周知的称为 机密计算(Confidential Computing, 有时也称为“可可 (CoCo)”)的场景,它需要保证虚拟机的安全性和机密性,哪怕是在受损或敌对的 host 计算机上运行。安全飞地(secure enclaves)和加密内存(encrypted memory)等技术已被开发出来,以保护虚拟机免受 host 的窥探侵害;这些技术有一天可能按照预期工作,但它们绝对依赖于可信的随机数据。如果在已经知道随机种子的情况下启动“机密”虚拟机,那么游戏可能在还没开始之前就已经注定 game over 了。

启动时熵的可用性长期以来一直是 Linux 系统的问题,所以已经开发了许多机制来尽可能快地为随机数生成器确定种子。这些机制包括使用引导加载程序注入的随机数据以及从环境中收集熵。然而,机密计算系统无法信任这种类型的输入信息。引导加载程序受主机控制,环境熵也是如此。正如 Reshetova 解释 的那样,主机能够控制诸如计时器到期和中断传递之类的事件。唯一不在主机控制之下的熵源是硬件随机数生成器(至少在理论上)。如果这也遭到破坏,那么整个机密计算的愿景就会化为泡影。

该怎么办?

从一开始,这个梦想就在内核圈子里就引起了不少争议,这次也一上来就有这方面的观点,Donenfeld 直接询问:“这个 CoCo VM 的东西是不是真的需求?最终保护客户机免受主机攻击是否真的可行?”然而,接下来的大部分讨论都集中在合适的应对措施应该是什么。

在机密计算用例之外,人们普遍认为什么都不需要做。打算在 RDSEED 或 RDRAND 失败时添加一个 warning(如 Shutemov 在讨论一开始提出的),但这似乎也不是正确的做法。许多系统运行时启用了panic_on_warn;在这样的系统上,warning 将导致系统 panic。这将把随机数生成器失败转变为拒绝服务问题。即使在这种情况下,如果早期引导期间发生失败,发出 warning 似乎也是值得的;如果发生这种情况,要么是随机数生成器坏了,要么显然有某种攻击正在进行。

当系统在保密计算模式下运行时,情况就有些复杂了。毕竟这不是内核整体公认的一个运行模式;Ts'o 建议为此目的添加一个全局标志,因为内核的其他部分最终很可能也需要它。但即使有了这个 flag,也有许多备选方案需要选择;Donenfeld 对这些方案进行了详细说明。可以归结为内核是否应该在失败时发出 warning(或 panic),是否应该在任何时候都这样做,以及这种措施是否应该在“保密计算模式”中改变。

显而易见的共识似乎是,先要直接对失败的操作进行重试,正如已经为 RDRAND 所做的那样。即使单个 RDRAND 可以被迫失败,让它连续十次都失败也是一个更难出现的情况。然而,应该记住,正如 Reshetova指出的,host 控制了 guest 的调度,并且理论上来说可以影响这个 retry 循环。如果确保每次 retry 都是在随机数生成器被耗尽的那时来运行,它们将永远不会成功。

至少,如果这些指令在早期引导期间失败,应该发出 warning,因为这是表明事情不太对的一个明显的迹象。对于保密计算案例来说,随机数失败意味着系统无法提供整个架构所依赖的保障,因此系统应该直接拒绝运行。这可以通过 panic 来实现,或者对 RDRAND 指令进行无限循环调用,如果指令永远不成功,就相当于把虚拟机锁住了。

除此之外,真的没有太多需要做的事情。

不过,有一部分讨论隐藏在背后,那就是这个担忧似乎已经在 CPU 供应商内部引起了一场慌乱,他们在确定问题的严重程度以及需要做些什么(如果有的话)。为了避免大家认为这是一个 Intel 特有的问题,Berrangé报告了在一些 AMD 处理器上强制出现高失败率的做法。这些讨论的结果可能会产生一些文档、或者 microcode 升级,以及未来处理器中的设计方案变更。

与此同时,随机数生成器耗尽的前景对大多数用户来说都不太用担心;看来不太可能用来威胁到现实世界中的系统。对于保密计算人群来说,这只是必须缓解的潜在威胁中肯定存在的无尽列表中的又一项而已。人们会采取措施来解决问题,我们都可以收起干草叉,回去继续观察有关保密计算是否可以真正实现的争论。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

e6e71553b3b2bf07246b9b48297e669d.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值