dstu_core/randombytes.rs
1//! `randombytes` equivalent (`docs/dstu-crypto-project.md` "Mapping onto the libsodium API",
2//! `docs/TASKS.md` T-72, `docs/DECISIONS.md` D-48) - not a DSTU primitive. Wraps the OS CSPRNG (`getrandom`),
3//! same as libsodium's own `randombytes_buf` does.
4//!
5//! `hazmat` primitives never generate their own randomness (D-09 - callers supply everything).
6//! `getrandom` fails to compile outright on an unrecognized bare-metal target (`docs/DECISIONS.md`
7//! D-04's addendum) unless a backend is selected - so pulling it in is opt-in, never bundled into
8//! a bare `no_std` build with no way to say no. Two ways to opt in: the `std` feature (assumes a
9//! real OS, `getrandom` picks its OS backend automatically), or the narrower `getrandom` feature
10//! (`docs/TASKS.md` T-123, `docs/DECISIONS.md` D-74) for `no_std` targets - an embedded caller who has
11//! configured one of `getrandom`'s own non-OS backends (most commonly `custom`, via
12//! `--cfg getrandom_backend="custom"` plus their own `extern "Rust" fn __getrandom_v03_custom`;
13//! see <https://docs.rs/getrandom/latest/getrandom/#custom-backend>) can enable this feature alone
14//! and use `randombytes_buf` without pulling in `std`/`alloc` at all. This crate does not implement
15//! its own pluggable-backend registry - `getrandom` 0.3 already *is* the mechanism libsodium's
16//! `randombytes_set_implementation()` plays the same role for (capability parity, not mechanism
17//! parity: `getrandom`'s selection is a compile-time/link-time choice the final binary makes, not
18//! a runtime-swappable function pointer) - building a second one here would duplicate an
19//! already-established primitive `docs/DECISIONS.md` D-03/D-04 already rejected doing for the RNG itself.
20
21use core::fmt;
22
23/// The OS CSPRNG failed to produce randomness (e.g. the platform's entropy source is transiently
24/// unavailable). See [`getrandom::Error`] for the possible underlying causes.
25#[derive(Debug)]
26pub struct RandomError(getrandom::Error);
27
28impl fmt::Display for RandomError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 write!(f, "OS CSPRNG error: {}", self.0)
31 }
32}
33
34impl core::error::Error for RandomError {}
35
36/// Fills `buf` with cryptographically secure random bytes from the OS CSPRNG.
37///
38/// # Errors
39///
40/// Returns [`RandomError`] if the OS CSPRNG is unavailable or fails.
41pub fn randombytes_buf(buf: &mut [u8]) -> Result<(), RandomError> {
42 getrandom::fill(buf).map_err(RandomError)
43}