LWN:让内核支持符合FIPS规范的随机数!
共 5862字,需浏览 12分钟
·
2021-12-22 20:39
关注了就能看到更多这么棒的文章哦~
FIPS-compliant random numbers for the kernel
By Jake Edge
December 7, 2021
DeepL assisted translation
https://lwn.net/Articles/877607/
Linux 随机数生成器(RNG, random-number generator)引出了大量的关注(和工作),尽管它是(或者说应该是)内核中一个相当小的组件。原因的一部分是因为随机数以及其质量对一些安全保护措施是极为重要的,从生成不可预测的 IP 包序列号到加密密钥都需要它。Stephan Müller 最近发布的第 43 版 Linux 随机数生成器(LRNG)patch 跟之前的版本一样,肯定无法合入。但围绕这组 patch 的讨论可能会引出对一些发行版很必要的一个功能的支持。
LRNG 这组 patch set 的封面标题是 "/dev/random - a new approach",这是事实,但也肯定会引出很多感到疑惑的回应,也可能会导致 patch 完全被忽略。正如在讨论中所重申的那样,内核开发通常不会采用 "全盘替换(wholesale replacement) "的方式。相反,功能通常是慢慢地、一点一点地增加上来的。但是 LRNG 的目的是要成为现有内核 RNG 的替代品,同时又添加了一系列的新功能。其实其中一些功能如果能从中分离出来,可能会很受欢迎。
Müller 提供了一组 ppt 来对 LRNG 进行了很好的概述。多年来,内核 RNG 一直有一个困难,就是如何在启动时保证收集足够的熵来确保能满足加密强度需求的随机数,尤其是对于虚拟机或者那些没有多少来自磁盘中断等的熵的系统中(比如使用 SSD 的系统)。LRNG 在启动时利用 CPU execution-time jitter (执行时间的抖动)以及其他一些技术来更快地收集熵。正如他在 LRNG 论文中所述,这种熵收集的方式符合美国国家标准与技术研究所(NIST)的 SP 800-90B 标准。此外,LRNG 将熵的各个来源结合起来时采用的技术具有完整文档以及数学论证,而不是目前内核 RNG 中采用的不正式的机制(informal mechanism)。
第一个 patch 包括 LRNG framework 中对熵的收集和处理的部分。提供了一个符合 NIST SP 800-90A 的 determinitic RNG(DRNG),但它也允许在框架内使用其他的 DRNG 实现。但事实上它是作为了现有 RNG 的直接替代品,意味着它取代了所有这部分代码。现有的代码其实是可以正常工作的,也许确实有一些已知的限制,但是采用一个新的实现来 "重新开始" 的做法肯定会有一些危险性。
除此之外,讨论中的几个人对 NIST 标准(也称为 FIPS 标准)的价值也持有怀疑态度。Jason A. Donenfeld 说:
你又把这个改动重新发布出来了,然而我仍然认为这不是正确的设计,也不是正确的方向。这里专门把 extended configurability("flexibility")作为明确目标,或者专门要与 FIPS 兼容,我不认为这些做法代表了好的方向,我认为这引入了新的问题,而不是解决任何现有问题。虽然有一些方法可以(甚至应该)要改进目前的 RNG,哪怕是重写,但你现在的这种做法仍然不是正确的做法,无论你发布多少次都是一样。
但 Müller 指出,一些发行版正在自己背负一些 patch 从而能做到符合 FIPS 的要求,这导致了内核中的 cryptographic RNG 方案的碎片化。LRNG 背后的想法是希望无论选择哪种 DRNG,都能确保所产生的随机数是以一种安全的方式产生的。此外,他说他没有收到关于 LRNG 设计的抱怨,而他在这一过程中根据多位 Linux 开发者的建议纳入了很多改动。这组 patch 的 change log 可以追溯到 2016 年,其中能看到不少的这类改动。
Distributions and FIPS
Greg Kroah-Hartman 想知道发行版中背负的 FIPS 合规性 patch 的具体情况。具体来说他想知道:"为什么发行版没有向 upstream 提交他们的改动?" 在 RHEL crypto 团队的 Simo Sorce 回答说:"我们没有向 upstream 提交,是因为这些都是一些 hack 的做法,我们清楚这一点,而且我们知道它们不是一个长期的解决方案。" 他说,Red Hat 确实需要某种方式能使其产品符合 FIPS 标准。
但是 Kroah-Hartman 说。"今天能起作用的 hack 做法,就是迈向真正解决方案的一步。" 他重申,要想让能符合 FIPS 规范的代码进入内核,需要的是演化(evolution),而不是完全替代随机数生成子系统。"从那些已知的、有效的、能通过认证的 hack 做法中着手。先提交这些改动,让我们从那里开始。"
同样,John Haxby 也说甲骨文也有一个 patch,可以在启动时或每次写入 sysfs 文件的时候来选择启用符合 FIPS 标准的 RNG。在 FIPS 模式下,它总是修改 DRNG 的 seed 为 jitter 熵。他说,对甲骨文来说,自己背负这样的 patch 补丁是 "not healthy",但这是权宜之计。他更希望在 upstream 上能有大家都可以用的东西,但暂时先用这个 patch 来做为一个临时变通的办法:
我们自己打上这个 patch 只是因为认证的要求发生了变化,而这个 patch 是解决当前问题的最快速和最简单的方法。它不能解决未来的问题,下次我们或者其他人尝试 FIPS 认证时,都会需要一个不同的/dev/random 方案,因为无论是旧的方案还是我们的快速 hack 的解决方法,实际上都是不可接受的。
Kroah-Hartman 建议说,这个 patch 也是一个很好的起点:"现在,与'重写整个随机数发生器'相比,这是一个更小、更简单、更容易理解的改动"。他说,如果那些需要符合 FIPS 标准的人可以配合起来一起工作,从而让代码进入 mainline,这可能是一个更容易的途径:
但是,仅仅为此而再专门添加一个独立随机子系统就不是一个好主意了,这也是这组 patch set 一直被内核开发者们忽视的一个主要原因。
Sorce 也回复了 Donenfeld,指出 "FIPS 对我们来说是必不可少的,任何设计方案都包括一个可以通过 FIPS 认证的选项"。Müller 一直在与发行版和标准组织合作,来收集和实现这些要求。在 Sorce 的另一封邮件中,他描述了其中的一些工作:
这些 patch 并不是凭空生成的,Stephan 基本上是提炼了多个供应商以及监管机构之间的讨论(你可以看到他有来自 BSI 的 review,并且 NIST 的要求在这里也有充分体现)。
他解决了几个我可以列举出来的需求,但注意这些并不是一个完整清单:性能(尤其是在 NUMA 系统上),不会在启动时由于缺乏熵而被卡住,遵循 NIST/BSI 规范,非常灵活因此针对未来的监管要求可以很容易地被集成进来推到 upstream 之上。
More FIPS
Kroah-Hartman 还是宁愿看到这里能遵循正常的内核开发路径。"记住,内核开发的正确方式是进化(evolution),而不是 intelligent design :)"。但是,正如 Müller 所指出的,在 2020 年 9 月就有一个 patch set 发布出来给大家讨论,它就是将目前的 RNG 通过 evolution 的方式来改为符合要求的 RNG,而那个 patch set 从来没有什么真正进展。Kroah-Hartman 问道:"那可是一大堆 patch,其中一些看起来很合理,它们后来进展如何?" Müller 说,答案是:"完全没有讨论,完全没有一个被合入"。
Müller 还说,LRNG 实际上并没有取代内核中现有的 RNG,它只是提供了一种使用方案的方法:
补充说明一下:LRNG 的 patch set 并没有取代 random.c,而是提供了一个额外的实现,可以在编译时来选择切换。我的印象中在内核的其他领域如文件系统、内存分配器等等,这是一种很正常的做法。
Kroah-Hartman 说,虽然在某些领域可能确实有必要同时拥有多个 upstream 的实现方案,但内核 RNG 并不算是这种领域。除此之外,内核 RNG 还在内核的多个地方使用。"很可能,你真的不希望内核内的调用是来自'random-government-crippled-specification' (也就是来自某个政府机构随意定义出来的规范) 方式实现,对吗?" Sorce 并不同意这个说法:
当我们的客户被要求使用 FIPS 认证的加解密方式时,他们也希望将其用在内核里的加解密上,而且通常来说,他们也希望使用一个可以通过认证的随机数来源。
他很理解,由于历史上的 Dual EC DRBG 之类的问题,人们在信任政府机构方面总会很犹豫,但 NIST 的规范并没有强制要求使用某种特定的算法,它的要求都是为了能允许多种不同的实现方式。此外:
该规范定义得相当彻底,其中提供了合理的要求,以及 self-test 来确保代码编写错误不会导致返回一些非随机的数值。
Maintainer questions
但是,在遵循 evolution 方式来改变内核 RNG 方面还有一个问题,Sorce 说:
这里的主要问题是,如果随便某个设备的维护者完全不参与讨论、也不合入那些明显的 bug fix,而且根本不参与进来,那么我们怎么能达到这个目的?
你的计划需要一个积极的维护者来引导这些改动,并与提出这些改动的人进行交流,从而协商出最佳结果。但这并没有发生,所以目前这条道路似乎被堵死了。
Ted Ts'o 是内核 RNG 的维护者,但在这次以及其他一些关于该子系统的改动和 fix 的讨论中明显缺席了。Kroah-Hartman 似乎对上面这种 bug fix 没有被采纳的说法持怀疑态度,但 Eric Biggers 列举了几个最终被其他维护者(其中一个是 Kroah-Hartman)合入之前一直被搁置的 fix 和清理工作。Biggers 总结说:"因此,不幸的是,就我所知,Ted 不再维护 random.c 了。"
Donenfeld 说,他愿意 review 对内核 RNG 的 fix 和改进,但提醒说他担心 FIPS 的要求可能过于宽泛:
因此,我们希望实现最好的 RNG 的目标,似乎有可能与获得合规认证的目标是互相冲突的,因为那个认证有点越界了。
[我希望内核有一个优秀的 CSPRNG [加密安全伪随机数发生器,cryptographically-secure pseudorandom number generator],从密码学的角度,从性能的角度,从 API 的角度。我认为这些目标与内核的一般开发方式是一致的。我认为把外部合规性的目标放在所有目标的最前面,大大偏离了内核的开发方式,甚至会分散了内核的开发精力。
[具体来说,我认为如果你改变你的观点,从 "我们如何改变 RNG 的算法来符合 FIPS " 变为 "我们如何在 FIPS 的限制之内进行一些调整,使客户想要的东西对 RNG 实现的质量的影响能降到最低、避免引入不当的维护负担。" 这意味着:不要把 RNG 重构成一些大型的抽象层并支持可以插拔来使用多种不同的实现方案,不要在一个巨大的 patch set 中重写整个东西,不要增加不相干的一些内容。相反,先做一些非常、非常小的事情,这将大大减少争议。
Sorce 对这一方法表示赞同,Haxby 说他会发布 Oracle 的 patch,来作为一种可能的前进方向。我们所看到的是,至少在某种程度上,是一个新的维护者出现,自愿来帮助解决内核 RNG 的问题,Ts'o 也支持这个决定。如果能提出一个更加符合 evolution 方式的修改方法,而不仅仅是 "因为 FIPS 有要求" 来进行修改,那么内核 RNG 方案似乎可以在避免被全面替换从而带来动荡的情况下也能达到合规的(compliance)要求。Sandy Harris 提出了另一种可能性,就是 FIPS 的要求其实也可以用现有的 RNG 来满足,但这里有一些需要调整的地方:
[……]事实上,他们的 DRNG 的设计中需要依赖一个外部的随机比特源(external source of random bits)。然而,它要求这个来源必须要经过认证(be certified),这对我们来说是个问题。英特尔等公司可能会让他们的随机数指令能通过认证,而 crypto 供应商或 SOC 芯片的供应商可能也会让他们的随机数硬件来获取认证,但是内核社区并不负责做这个事情。
我认为内核的熵收集程序已经足够好了,它们原则上可以通过认证,但这将涉及一些工作量以及不少资金。
很明显,至少对于企业版来说,还是需要一些解决方案的。Müller 的 patch 提供了一个符合 FIPS 标准的机制,并且对性能的影响很小,甚至可能比现有的实现方式更好,同时还解决了一些其他问题。这里所使用的技术可以形成比较好的基础,后续就只要相对比较少的改动,这可能会使内核 RNG 的所有用户都受益。现在的 patch set 是无法落地的,但是,如果运气好,再加上一些毅力,那么我们也是可以通过遵循通常的内核开发策略来满足 FIPS 的要求的。只能等时间来告诉我们答案了。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~