内核 Random、CRNG 与用户接口
1. 目标
random.c聚合不可信或不同质量的输入,维护cryptographic RNG状态,并向内核和用户空间提供随机字节。它不把某个HWRNG输出原样转交应用。
2. 输入来源
典型输入:
- interrupt timing;
- device/input timing;
- bootloader seed;
- CPU RNG;
- hardware generator;
- architecture/firmware randomness;
- 用户向random/urandom写入的数据。
数据可以混入pool但不一定获得entropy credit。Credit决定CRNG何时被认为初始化。
3. 初始化阶段
系统早期CRNG可能未ready。代码维护初始化状态和waitqueue:
1 | collect entropy |
密码、长期密钥和TLS随机数必须等待CRNG ready。
4. /dev/random
Linux 6.1中,CRNG初始化后/dev/random与urandom都基于同一安全生成器;主要差别是random在初始化前阻塞。
Read支持:
- blocking;
O_NONBLOCK;- signal中断;
- iter I/O;
- poll ready。
不要用“每读取一次就消耗固定entropy位”的旧模型解释现代实现。
5. /dev/urandom
初始化前历史上可返回早期输出,因此敏感程序更推荐getrandom(),它能显式等待ready且不依赖device node。
初始化后适合大多数随机需求。
6. getrandom
Flags包括:
GRND_NONBLOCK;GRND_RANDOM;GRND_INSECURE。
默认调用在CRNG ready前等待。GRND_INSECURE允许早期输出,只适合明确不要求密码学安全的场景。
7. 内核API
get_random_bytes();get_random_u32/u64();get_random_long();get_random_bytes_wait();add_device_randomness();add_hwgenerator_randomness();wait_for_random_bytes()。
Driver应使用API,不应自行read /dev/urandom。
8. 写入语义
向random/urandom写数据会mix进状态,但普通write不会自动声明这些数据含有可信entropy。只有受控内核路径可credit entropy。
这防止任意用户通过可预测数据欺骗CRNG ready。
9. Reseed
CRNG按时间/生成量及新entropy reseed。Per-CPU batched random减少全局锁竞争,适合非密钥的频繁u32/u64使用。
10. Trust配置
RANDOM_TRUST_CPU和RANDOM_TRUST_BOOTLOADER控制CPU/boot seed是否被credit,而不是是否mix。
RK3588产品应评估:
- Bootloader是否每次提供唯一高质量seed;
- SMCCC/SoC TRNG是否可信;
- 克隆镜像是否保存并更新random seed;
- 安全启动链是否保护seed注入。
11. 并发
Random fast path使用per-CPU状态、锁、RCU和waitqueue降低竞争。Entropy输入可来自IRQ,不能在该路径睡眠。
用户read大buffer会分块生成并检查signal/reschedule。
12. 与HWRNG区别
/dev/random/urandom |
/dev/hwrng |
|---|---|
| 内核CSPRNG输出 | 当前硬件源原始输出 |
| 混合多源、reseed | 单一selected hwrng |
| 适合密钥 | 需自行健康评估 |
| 初始化状态明确 | 可因硬件故障返回错误 |
应用通常不应直接用/dev/hwrng替代getrandom()。
正在加载留言…