Skip to content

Add RngProtocol to uefi-raw and use it from uefi #778

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 3 commits into from
Apr 29, 2023
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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions uefi-raw/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version = "1.68"
bitflags = "1.3.1"
ptr_meta = { version = "0.2.0", default-features = false }
uefi-macros = "0.11.0"
uguid = "2.0.0"

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
3 changes: 3 additions & 0 deletions uefi-raw/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#[macro_use]
mod enums;

pub mod protocol;

mod status;

pub use status::Status;
pub use uguid::{guid, Guid};
7 changes: 7 additions & 0 deletions uefi-raw/src/protocol/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Protocol definitions.
//!
//! Protocols are sets of related functionality identified by a unique
//! ID. They can be implemented by a UEFI driver or occasionally by a
//! UEFI application.

pub mod rng;
54 changes: 54 additions & 0 deletions uefi-raw/src/protocol/rng.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! `Rng` protocol.

use crate::{guid, Guid, Status};

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!("00000000-0000-0000-0000-000000000000"),

/// 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!("e43176d7-b6e8-4827-b784-7ffdc4b68561"),

/// ALGORITHM_SP800_90_HASH_256
ALGORITHM_SP800_90_HASH_256 = guid!("a7af67cb-603b-4d42-ba21-70bfb6293f96"),

/// ALGORITHM_SP800_90_HMAC_256
ALGORITHM_SP800_90_HMAC_256 = guid!("c5149b43-ae85-4f53-9982-b94335d3a9e7"),

/// ALGORITHM_SP800_90_CTR_256
ALGORITHM_SP800_90_CTR_256 = guid!("44f0de6e-4d8c-4045-a8c7-4dd168856b9e"),

/// ALGORITHM_X9_31_3DES
ALGORITHM_X9_31_3DES = guid!("63c4785a-ca34-4012-a3c8-0b6a324f5546"),

/// ALGORITHM_X9_31_AES
ALGORITHM_X9_31_AES = guid!("acd03321-777e-4d3d-b1c8-20cfd88820c9"),
}
}

/// Rng protocol.
#[repr(C)]
pub struct RngProtocol {
pub get_info: unsafe extern "efiapi" fn(
this: *mut RngProtocol,
algorithm_list_size: *mut usize,
algorithm_list: *mut RngAlgorithmType,
) -> Status,

pub get_rng: unsafe extern "efiapi" fn(
this: *mut RngProtocol,
algorithm: *const RngAlgorithmType,
value_length: usize,
value: *mut u8,
) -> Status,
}

impl RngProtocol {
pub const GUID: Guid = guid!("3152bca5-eade-433d-862e-c01cdc291f44");
}
85 changes: 25 additions & 60 deletions uefi/src/proto/rng.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,15 @@
//! `Rng` protocol.

use crate::data_types::Guid;
use crate::proto::unsafe_protocol;
use crate::{guid, Result, Status, StatusExt};
use crate::{Result, Status, StatusExt};
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!("00000000-0000-0000-0000-000000000000"),

/// 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!("e43176d7-b6e8-4827-b784-7ffdc4b68561"),

/// ALGORITHM_SP800_90_HASH_256
ALGORITHM_SP800_90_HASH_256 = guid!("a7af67cb-603b-4d42-ba21-70bfb6293f96"),

/// ALGORITHM_SP800_90_HMAC_256
ALGORITHM_SP800_90_HMAC_256 = guid!("c5149b43-ae85-4f53-9982-b94335d3a9e7"),

/// ALGORITHM_SP800_90_CTR_256
ALGORITHM_SP800_90_CTR_256 = guid!("44f0de6e-4d8c-4045-a8c7-4dd168856b9e"),

/// ALGORITHM_X9_31_3DES
ALGORITHM_X9_31_3DES = guid!("63c4785a-ca34-4012-a3c8-0b6a324f5546"),

/// ALGORITHM_X9_31_AES
ALGORITHM_X9_31_AES = guid!("acd03321-777e-4d3d-b1c8-20cfd88820c9"),
}
}
pub use uefi_raw::protocol::rng::RngAlgorithmType;

/// Rng protocol
#[repr(C)]
#[unsafe_protocol("3152bca5-eade-433d-862e-c01cdc291f44")]
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,
}
#[unsafe_protocol(uefi_raw::protocol::rng::RngProtocol::GUID)]
pub struct Rng(uefi_raw::protocol::rng::RngProtocol);

impl Rng {
/// Returns information about the random number generation implementation.
Expand All @@ -61,20 +20,24 @@ impl Rng {
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())
.to_result_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
}
},
)
(self.0.get_info)(
&mut self.0,
&mut algorithm_list_size,
algorithm_list.as_mut_ptr(),
)
.to_result_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
}
},
)
}
}

Expand All @@ -87,6 +50,8 @@ impl Rng {
Some(algo) => algo as *const RngAlgorithmType,
};

unsafe { (self.get_rng)(self, algo, buffer_length, buffer.as_mut_ptr()).to_result() }
unsafe {
(self.0.get_rng)(&mut self.0, algo, buffer_length, buffer.as_mut_ptr()).to_result()
}
}
}