diff --git a/src/agent/src/random.rs b/src/agent/src/random.rs index 4713134a8..c2506ac24 100644 --- a/src/agent/src/random.rs +++ b/src/agent/src/random.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // -use anyhow::Result; +use anyhow::{ensure, Result}; use nix::errno::Errno; use nix::fcntl::{self, OFlag}; use nix::sys::stat::Mode; @@ -13,7 +13,7 @@ use tracing::instrument; pub const RNGDEV: &str = "/dev/random"; pub const RNDADDTOENTCNT: libc::c_int = 0x40045201; -pub const RNDRESEEDRNG: libc::c_int = 0x5207; +pub const RNDRESEEDCRNG: libc::c_int = 0x5207; // Handle the differing ioctl(2) request types for different targets #[cfg(target_env = "musl")] @@ -24,6 +24,9 @@ type IoctlRequestType = libc::c_ulong; #[instrument] pub fn reseed_rng(data: &[u8]) -> Result<()> { let len = data.len() as libc::c_long; + + ensure!(len > 0, "missing entropy data"); + fs::write(RNGDEV, data)?; let f = { @@ -41,8 +44,52 @@ pub fn reseed_rng(data: &[u8]) -> Result<()> { }; Errno::result(ret).map(drop)?; - let ret = unsafe { libc::ioctl(f.as_raw_fd(), RNDRESEEDRNG as IoctlRequestType, 0) }; + let ret = unsafe { libc::ioctl(f.as_raw_fd(), RNDRESEEDCRNG as IoctlRequestType, 0) }; Errno::result(ret).map(drop)?; Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::skip_if_not_root; + use std::fs::File; + use std::io::prelude::*; + + #[test] + fn test_reseed_rng() { + skip_if_not_root!(); + const POOL_SIZE: usize = 512; + let mut f = File::open("/dev/urandom").unwrap(); + let mut seed = [0; POOL_SIZE]; + let n = f.read(&mut seed).unwrap(); + // Ensure the buffer was filled. + assert!(n == POOL_SIZE); + let ret = reseed_rng(&seed); + assert!(ret.is_ok()); + } + + #[test] + fn test_reseed_rng_not_root() { + const POOL_SIZE: usize = 512; + let mut f = File::open("/dev/urandom").unwrap(); + let mut seed = [0; POOL_SIZE]; + let n = f.read(&mut seed).unwrap(); + // Ensure the buffer was filled. + assert!(n == POOL_SIZE); + let ret = reseed_rng(&seed); + if nix::unistd::Uid::effective().is_root() { + assert!(ret.is_ok()); + } else { + assert!(!ret.is_ok()); + } + } + + #[test] + fn test_reseed_rng_zero_data() { + let seed = []; + let ret = reseed_rng(&seed); + assert!(!ret.is_ok()); + } +}