安全加密的伪随机数生成器

本文档介绍了 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() 方法时:

  1. nonce 递增。

  2. 使用 ChaCha20 算法对输出缓冲区进行加密,同时使用 keynonce

此处,nonce 会针对每个 Draw() 请求递增,以确保不同的 结果。调用程序会提供缓冲区以执行就地加密。不限 使用缓冲区中的现有数据,因为它们不会影响 属性。

出现 AddEntropy() 请求时,key 通过混合 额外的熵:

k<sub>new</sub> = H(e || k<sub>old</sub>)

其中 k<sub>old</sub>k<sub>new</sub> 分别表示新旧keye 为输入字节,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 子系统安全通信的程序。