1 | //! `Rng` protocol. |
2 | |
3 | use crate::{data_types::Guid, guid, proto::unsafe_protocol , Result, Status}; |
4 | use core::{mem, ptr}; |
5 | |
6 | newtype_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" )] |
39 | pub 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 | |
53 | impl 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 | |