1//! `Rng` protocol.
2
3use crate::{data_types::Guid, guid, proto::unsafe_protocol, Result, Status};
4use core::{mem, ptr};
5
6newtype_enum! {
7 /// The algorithms listed are optional, not meant to be exhaustive
8 /// and may be augmented by vendors or other industry standards.
9 pub enum RngAlgorithmType: Guid => {
10 /// Indicates a empty algorithm, used to instantiate a buffer
11 /// for `get_info`
12 EMPTY_ALGORITHM = guid!("00000000-0000-0000-0000-000000000000"),
13
14 /// The “raw” algorithm, when supported, is intended to provide
15 /// entropy directly from the source, without it going through
16 /// some deterministic random bit generator.
17 ALGORITHM_RAW = guid!("e43176d7-b6e8-4827-b784-7ffdc4b68561"),
18
19 /// ALGORITHM_SP800_90_HASH_256
20 ALGORITHM_SP800_90_HASH_256 = guid!("a7af67cb-603b-4d42-ba21-70bfb6293f96"),
21
22 /// ALGORITHM_SP800_90_HMAC_256
23 ALGORITHM_SP800_90_HMAC_256 = guid!("c5149b43-ae85-4f53-9982-b94335d3a9e7"),
24
25 /// ALGORITHM_SP800_90_CTR_256
26 ALGORITHM_SP800_90_CTR_256 = guid!("44f0de6e-4d8c-4045-a8c7-4dd168856b9e"),
27
28 /// ALGORITHM_X9_31_3DES
29 ALGORITHM_X9_31_3DES = guid!("63c4785a-ca34-4012-a3c8-0b6a324f5546"),
30
31 /// ALGORITHM_X9_31_AES
32 ALGORITHM_X9_31_AES = guid!("acd03321-777e-4d3d-b1c8-20cfd88820c9"),
33 }
34}
35
36/// Rng protocol
37#[repr(C)]
38#[unsafe_protocol("3152bca5-eade-433d-862e-c01cdc291f44")]
39pub struct Rng {
40 get_info: unsafe extern "efiapi" fn(
41 this: &Rng,
42 algorithm_list_size: *mut usize,
43 algorithm_list: *mut RngAlgorithmType,
44 ) -> Status,
45 get_rng: unsafe extern "efiapi" fn(
46 this: &Rng,
47 algorithm: *const RngAlgorithmType,
48 value_length: usize,
49 value: *mut u8,
50 ) -> Status,
51}
52
53impl Rng {
54 /// Returns information about the random number generation implementation.
55 pub fn get_info<'buf>(
56 &mut self,
57 algorithm_list: &'buf mut [RngAlgorithmType],
58 ) -> Result<&'buf [RngAlgorithmType], Option<usize>> {
59 let mut algorithm_list_size = algorithm_list.len() * mem::size_of::<RngAlgorithmType>();
60
61 unsafe {
62 (self.get_info)(self, &mut algorithm_list_size, algorithm_list.as_mut_ptr()).into_with(
63 || {
64 let len = algorithm_list_size / mem::size_of::<RngAlgorithmType>();
65 &algorithm_list[..len]
66 },
67 |status| {
68 if status == Status::BUFFER_TOO_SMALL {
69 Some(algorithm_list_size)
70 } else {
71 None
72 }
73 },
74 )
75 }
76 }
77
78 /// Returns the next set of random numbers
79 pub fn get_rng(&mut self, algorithm: Option<RngAlgorithmType>, buffer: &mut [u8]) -> Result {
80 let buffer_length = buffer.len();
81
82 let algo = match algorithm.as_ref() {
83 None => ptr::null(),
84 Some(algo) => algo as *const RngAlgorithmType,
85 };
86
87 unsafe { (self.get_rng)(self, algo, buffer_length, buffer.as_mut_ptr()).into() }
88 }
89}
90