Skip to main content

vck_common/
rng.rs

1// SPDX-FileCopyrightText: 2026 JC-Lab <joseph@jc-lab.net>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! Pluggable cryptographic randomness source.
6//!
7//! `lib/common` is `no_std` and has no RNG of its own. The JVCK metadata store
8//! needs a fresh random salt every time it (re)encodes the EncryptedMetadata
9//! blob (see `jvck::metadata`), so the integrator installs a platform RNG once
10//! at startup:
11//!
12//! - kernel driver: a `BCryptGenRandom`-backed source, installed in `DriverEntry`;
13//! - host tests/tooling: any deterministic or `std`-backed source.
14//!
15//! The loader never re-encodes metadata (its volume is read-only), so it does
16//! not need to install a source.
17
18use crate::{VckError, VckResult};
19
20/// A cryptographically secure randomness source.
21pub trait RandomSource: Send + Sync {
22    /// Fill `buf` with random bytes, or return an error if randomness is
23    /// unavailable.
24    fn fill(&self, buf: &mut [u8]) -> VckResult<()>;
25}
26
27static RNG: spin::Once<&'static dyn RandomSource> = spin::Once::new();
28
29/// Install the process-wide randomness source. Idempotent — only the first call
30/// takes effect (subsequent calls are ignored), which keeps test setup simple.
31pub fn set_random_source(source: &'static dyn RandomSource) {
32    RNG.call_once(|| source);
33}
34
35/// Fill `buf` with random bytes from the installed source.
36///
37/// Returns `CryptoFailed` if no source has been installed — encoding metadata
38/// without a randomness source is a programming error (the integrator must call
39/// [`set_random_source`] at startup).
40pub fn fill_random(buf: &mut [u8]) -> VckResult<()> {
41    match RNG.get() {
42        Some(src) => src.fill(buf),
43        None => Err(VckError::CryptoFailed("no RandomSource installed")),
44    }
45}