Skip to content

Add rng protocole #386

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Added `BootServices::load_image` and `LoadImageSource`. Together these
replace `BootServices::load_image_from_buffer` and also allow an image
to be loaded via the `SimpleFileSystem` protocol.
- Added `Rng` protocol.

### Changed

Expand Down
1 change: 1 addition & 0 deletions src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ pub mod device_path;
pub mod loaded_image;
pub mod media;
pub mod pi;
pub mod rng;
pub mod shim;
132 changes: 132 additions & 0 deletions src/proto/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//! `Rng` protocol.

use crate::{data_types::Guid, proto::Protocol, unsafe_guid, Result, Status};
use core::{mem, ptr};

newtype_enum! {
/// The algorithms listed are optional, not meant to be exhaustive
/// and may be augmented by vendors or other industry standards.
pub enum RngAlgorithmType: Guid => {
/// Indicates a empty algorithm, used to instantiate a buffer
/// for `get_info`
EMPTY_ALGORITHM = Guid::from_values(
0x00000000,
0x0000,
0x0000,
0x0000,
0x000000000000,
),

/// The “raw” algorithm, when supported, is intended to provide
/// entropy directly from the source, without it going through
/// some deterministic random bit generator.
ALGORITHM_RAW = Guid::from_values(
0xe43176d7,
0xb6e8,
0x4827,
0xb784,
0x7ffdc4b68561,
),

/// ALGORITHM_SP800_90_HASH_256
ALGORITHM_SP800_90_HASH_256 = Guid::from_values(
0xa7af67cb,
0x603b,
0x4d42,
0xba21,
0x70bfb6293f96,
),

/// ALGORITHM_SP800_90_HMAC_256
ALGORITHM_SP800_90_HMAC_256 = Guid::from_values(
0xc5149b43,
0xae85,
0x4f53,
0x9982,
0xb94335d3a9e7,
),

/// ALGORITHM_SP800_90_CTR_256
ALGORITHM_SP800_90_CTR_256 = Guid::from_values(
0x44f0de6e,
0x4d8c,
0x4045,
0xa8c7,
0x4dd168856b9e,
),

/// ALGORITHM_X9_31_3DES
ALGORITHM_X9_31_3DES = Guid::from_values(
0x63c4785a,
0xca34,
0x4012,
0xa3c8,
0x0b6a324f5546,
),

/// ALGORITHM_X9_31_AES
ALGORITHM_X9_31_AES = Guid::from_values(
0xacd03321,
0x777e,
0x4d3d,
0xb1c8,
0x20cfd88820c9,
),
}
}

/// Rng protocol
#[repr(C)]
#[unsafe_guid("3152bca5-eade-433d-862e-c01cdc291f44")]
#[derive(Protocol)]
pub struct Rng {
get_info: unsafe extern "efiapi" fn(
this: &Rng,
algorithm_list_size: *mut usize,
algorithm_list: *mut RngAlgorithmType,
) -> Status,
get_rng: unsafe extern "efiapi" fn(
this: &Rng,
algorithm: *const RngAlgorithmType,
value_length: usize,
value: *mut u8,
) -> Status,
}

impl Rng {
/// Returns information about the random number generation implementation.
pub fn get_info<'buf>(
&mut self,
algorithm_list: &'buf mut [RngAlgorithmType],
) -> Result<&'buf [RngAlgorithmType], Option<usize>> {
let mut algorithm_list_size = algorithm_list.len() * mem::size_of::<RngAlgorithmType>();

unsafe {
(self.get_info)(self, &mut algorithm_list_size, algorithm_list.as_mut_ptr()).into_with(
|| {
let len = algorithm_list_size / mem::size_of::<RngAlgorithmType>();
&algorithm_list[..len]
},
|status| {
if status == Status::BUFFER_TOO_SMALL {
Some(algorithm_list_size)
} else {
None
}
},
)
}
}

/// Returns the next set of random numbers
pub fn get_rng(&mut self, algorithm: Option<RngAlgorithmType>, buffer: &mut [u8]) -> Result {
let buffer_length = buffer.len();

let algo = match algorithm {
None => ptr::null(),
Some(algo) => &algo as *const RngAlgorithmType,
};

unsafe { (self.get_rng)(self, algo, buffer_length, buffer.as_mut_ptr()).into() }
}
}
2 changes: 2 additions & 0 deletions uefi-test-runner/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
loaded_image::test(image, bt);
media::test(image, bt);
pi::test(bt);
rng::test(image, bt);

#[cfg(any(
target_arch = "i386",
Expand Down Expand Up @@ -60,6 +61,7 @@ mod device_path;
mod loaded_image;
mod media;
mod pi;
mod rng;
#[cfg(any(
target_arch = "i386",
target_arch = "x86_64",
Expand Down
37 changes: 37 additions & 0 deletions uefi-test-runner/src/proto/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use uefi::prelude::*;
use uefi::proto::rng::{Rng, RngAlgorithmType};
use uefi::table::boot::{BootServices, OpenProtocolAttributes, OpenProtocolParams};

pub fn test(image: Handle, bt: &BootServices) {
info!("Running rng protocol test");

let handle = *bt
.find_handles::<Rng>()
.expect_success("Failed to get Rng handles")
.first()
.expect("No Rng handles");

let rng = bt
.open_protocol::<Rng>(
OpenProtocolParams {
handle,
agent: image,
controller: None,
},
OpenProtocolAttributes::Exclusive,
)
.expect_success("Failed to open Rng protocol");
let rng = unsafe { &mut *rng.interface.get() };

let mut list = [RngAlgorithmType::EMPTY_ALGORITHM; 4];

let list = rng.get_info(&mut list).unwrap_success();
info!("Supported rng algorithms : {:?}", list);

let mut buf = [0u8; 4];

rng.get_rng(Some(list[0]), &mut buf).unwrap_success();

assert_ne!([0u8; 4], buf);
info!("Random buffer : {:?}", buf);
}
2 changes: 2 additions & 0 deletions xtask/src/qemu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ pub fn run_qemu(arch: UefiArch, opt: &QemuOpt) -> Result<()> {
// QEMU by defaults enables a ton of devices which slow down boot.
cmd.arg("-nodefaults");

cmd.args(&["-device", "virtio-rng-pci"]);

match arch {
UefiArch::AArch64 => {
// Use a generic ARM environment. Sadly qemu can't emulate a
Expand Down