本文档介绍了 Zircon 的加密安全伪造型的设计, 随机数字生成器 (CPRNG),包括其算法、(重新)播种过程、 和熵源。
简介
Zircon 的内置 CPRNG 通过
非阻塞方式。用户空间程序可以通过
zx_cprng_draw()
系统调用。
Zircon 的 CPRNG 只信任可从
因为内核之外的任何内容,例如驱动程序,
被视为用户空间程序,不可信任。CPRNG 正常运行
安全无害,但至少需要选择以下来源之一。不过,
用户空间程序可通过
zx_cprng_add_entropy()
系统调用。
算法
Zircon 的 CPRNG 是一个伪随机数生成器。其实现位于
时间:zircon/kernel/lib/crypto
。它支持两种运算:Draw()
和
AddEntropy()
,对应于上述两个系统调用。通过
内部状态由 256 位 key
和 128 位 nonce
组成。key
必须
因为 CPRNG 输出可通过
。最开始,使用一些随机字节初始化 key
(请参阅下一部分),并且 nonce
初始化为 0。
调用 Draw()
方法时:
nonce
递增。使用 ChaCha20 算法对输出缓冲区进行加密,同时使用
key
和nonce
。
此处,nonce
会针对每个 Draw()
请求递增,以确保不同的
结果。调用程序会提供缓冲区以执行就地加密。不限
使用缓冲区中的现有数据,因为它们不会影响
属性。
出现 AddEntropy()
请求时,key
通过混合
额外的熵:
k<sub>new</sub> = H(e || k<sub>old</sub>)
其中 k<sub>old</sub>
和 k<sub>new</sub>
分别表示新旧key
,
e
为输入字节,H
为 SHA256 哈希函数,||
为
表示串联。哈希中包含旧键,
调用方,例如调用 zx_cprng_add_entropy()
的用户空间程序
完全清除旧的 key
,并将其替换为这些程序控制的组件。
播种和重新播种
调用 AddEntropy()
方法可执行 Zircon 的初始种子
CPRNG.虚拟内存 ASLR 需要初始种子,因此第一次调用
AddEntropy()
方法发生在启动序列的早期,
启动。必须设置初始种子,CPRNG 才能
在添加足够的熵之前,Draw()
方法会阻塞。
初始种子设定后,系统会创建一个线程,以每 30 秒重新播种一次 CPRNG
AddEntropy()
方法,秒。这样可以确保正向加密(
可以保证自上次更新后 CPRNG 之前的所有输出的机密性,
即使其内部状态受到攻击)。
熵源
Zircon 的 CPRNG 可通过多种熵源进行播种, 补种:
内核 cmdline 选项
kernel.entropy-mixin
中的熵,记录在 kernel_cmdline.md。来自硬件 RNG 的熵(例如 x86 设备上的
RDSEED
指令),以及 其他硬件专用 RNG
内核 cmdline 仅在初始种子设定时使用,因为它是一个常量
在启动时传入且仅限一次性使用。硬件熵和抖动
熵可用于初始种子和后播种子。为了确保 CPRNG
充分(重新)引出选定的熵源,您就可以使用
内核 cmdline kernel.cprng-(re)seed-require.*
选项。如需更多信息
请参阅 kernel_cmdline.md。
可能存在其他可用的熵源,例如可信平台模块 (TPM),但我们目前还没有针对用户空间建立强大的框架 与内核中的 CPRNG 子系统安全通信的程序。