Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit 3ec862a

Browse files
committed
Refs #164 -- expose the kernel's CSPRNG, safely
1 parent 11ae6d2 commit 3ec862a

File tree

5 files changed

+40
-0
lines changed

5 files changed

+40
-0
lines changed

build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@ const INCLUDED_FUNCTIONS: &[&str] = &[
2525
"_copy_from_user",
2626
"alloc_chrdev_region",
2727
"unregister_chrdev_region",
28+
"wait_for_random_bytes",
29+
"get_random_bytes",
30+
"rng_is_initialized",
2831
];
2932
const INCLUDED_VARS: &[&str] = &[
3033
"EINVAL",
3134
"ENOMEM",
3235
"ESPIPE",
3336
"EFAULT",
37+
"EAGAIN",
3438
"__this_module",
3539
"FS_REQUIRES_DEV",
3640
"FS_BINARY_MOUNTDATA",

src/bindings_helper.h

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/cdev.h>
22
#include <linux/fs.h>
33
#include <linux/module.h>
4+
#include <linux/random.h>
45
#include <linux/slab.h>
56
#include <linux/uaccess.h>
67
#include <linux/version.h>

src/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ impl Error {
1010
pub const ENOMEM: Self = Error(-(bindings::ENOMEM as i32));
1111
pub const EFAULT: Self = Error(-(bindings::EFAULT as i32));
1212
pub const ESPIPE: Self = Error(-(bindings::ESPIPE as i32));
13+
pub const EAGAIN: Self = Error(-(bindings::EAGAIN as i32));
1314

1415
pub fn from_kernel_errno(errno: c_types::c_int) -> Error {
1516
Error(errno)

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod error;
1313
pub mod file_operations;
1414
pub mod filesystem;
1515
pub mod printk;
16+
pub mod random;
1617
pub mod sysctl;
1718
mod types;
1819
pub mod user_ptr;

src/random.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use core::convert::TryInto;
2+
3+
use crate::{bindings, c_types, error};
4+
5+
/// Fills `dest` with random bytes generated from the kernel's CSPRNG. Ensures
6+
/// that the CSPRNG has been seeded before generating any random bytes, and
7+
/// will block until it's ready.
8+
pub fn getrandom(dest: &mut [u8]) -> error::KernelResult<()> {
9+
let res = unsafe { bindings::wait_for_random_bytes() };
10+
if res != 0 {
11+
return Err(error::Error::from_kernel_errno(res));
12+
}
13+
14+
unsafe {
15+
// TODO: convert `unwrap` to proper error handling
16+
bindings::get_random_bytes(
17+
dest.as_mut_ptr() as *mut c_types::c_void,
18+
dest.len().try_into().unwrap(),
19+
);
20+
}
21+
Ok(())
22+
}
23+
24+
/// Fills `dest` with random bytes generated from the kernel's CSPRNG. If the
25+
/// CSPRNG is not yet seeded, returns an `Err(EAGAIN)` immediately. Only
26+
/// available on 4.19 and later kernels.
27+
#[cfg(kernel_4_19_0_or_greater)]
28+
pub fn getrandom_nonblock(dest: &mut [u8]) -> error::KernelResult<()> {
29+
if !unsafe { bindings::rng_is_initialized() } {
30+
return Err(error::Error::EAGAIN);
31+
}
32+
getrandom(dest)
33+
}

0 commit comments

Comments
 (0)