firmware_uefi/service/
crypto.rs1use crate::UefiDevice;
7use guestmem::GuestMemoryError;
8use uefi_specs::hyperv::crypto::CryptoCommandDescriptor;
9use uefi_specs::uefi::common::EfiStatus;
10
11impl UefiDevice {
12 pub(crate) fn crypto_handle_command(&mut self, desc_addr: u64) {
13 let mut desc: CryptoCommandDescriptor = match self.gm.read_plain(desc_addr) {
14 Ok(desc) => desc,
15 Err(err) => {
16 tracelimit::warn_ratelimited!(
17 error = &err as &dyn std::error::Error,
18 "Could not read CryptoCommandDescriptor from guest memory",
19 );
20 return;
21 }
22 };
23
24 let status = match self.crypto_handle_command_inner(desc_addr, desc) {
25 Ok(status) => status,
26 Err(err) => {
27 tracelimit::warn_ratelimited!(
28 error = &err as &dyn std::error::Error,
29 "Guest memory error while handling crypto command",
30 );
31 EfiStatus::DEVICE_ERROR
32 }
33 };
34 desc.status = status.into();
35
36 if let Err(err) = self.gm.write_plain(desc_addr, &desc) {
37 tracelimit::warn_ratelimited!(
38 error = &err as &dyn std::error::Error,
39 "Could not write CryptoCommandDescriptor into guest memory",
40 );
41 }
42 }
43
44 fn crypto_handle_command_inner(
45 &mut self,
46 desc_addr: u64,
47 desc: CryptoCommandDescriptor,
48 ) -> Result<EfiStatus, GuestMemoryError> {
49 use uefi_specs::hyperv::crypto::CryptoCommand;
50
51 let command_addr = desc_addr + size_of_val(&desc) as u64;
52
53 match desc.command {
54 CryptoCommand::GET_RANDOM_NUMBER => {
55 use uefi_specs::hyperv::crypto::CryptoGetRandomNumberParams;
56 const MAXIMUM_RNG_SIZE: usize = 8;
59
60 let command: CryptoGetRandomNumberParams = self.gm.read_plain(command_addr)?;
61 let buffer_size = command.buffer_size as usize;
62
63 if buffer_size > MAXIMUM_RNG_SIZE {
64 return Ok(EfiStatus::INVALID_PARAMETER);
65 }
66
67 let random_number = &mut [0; MAXIMUM_RNG_SIZE][..buffer_size];
68 getrandom::fill(random_number).expect("rng failure");
69
70 self.gm
71 .write_at(command.buffer_address.into(), random_number)?;
72
73 Ok(EfiStatus::SUCCESS)
74 }
75 command => {
76 tracelimit::warn_ratelimited!(?command, "unknown or unhandled crypto command");
77 Ok(EfiStatus::DEVICE_ERROR)
78 }
79 }
80 }
81}