本文档介绍了 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 子系统安全通信的程序。