diff --git a/Cargo.lock b/Cargo.lock index a2fb7d5f1..d0c92e760 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,6 +300,17 @@ dependencies = [ "serde", ] +[[package]] +name = "bitfield-struct" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac32db62a43cf33353ce30b4a208b08193ea2086a1c6c004acb0073c706a29d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.31", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -478,6 +489,15 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "crc64" version = "1.0.0" @@ -938,6 +958,8 @@ dependencies = [ "byteorder", "env_logger", "iced-x86", + "igvm", + "igvm_defs", "kvm-bindings", "kvm-ioctls", "libc", @@ -967,6 +989,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "igvm" +version = "0.1.0" +source = "git+https://github.com/microsoft/igvm?branch=main#c1b0201d8286cb23b9f30cb16ba435484666cfa3" +dependencies = [ + "bitfield-struct", + "crc32fast", + "hex", + "igvm_defs", + "open-enum", + "range_map_vec", + "thiserror", + "tracing", + "zerocopy", +] + +[[package]] +name = "igvm_defs" +version = "0.1.0" +source = "git+https://github.com/microsoft/igvm?branch=main#c1b0201d8286cb23b9f30cb16ba435484666cfa3" +dependencies = [ + "bitfield-struct", + "open-enum", + "static_assertions", + "zerocopy", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1294,6 +1343,26 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "open-enum" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9807f1199cf84ec7cc801a79e5ee9aa5178e4762c6b9c7066c30b3cabdcd911e" +dependencies = [ + "open-enum-derive", +] + +[[package]] +name = "open-enum-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "894ae443e59fecf7173ab3b963473f44193fa71b3c8953c61a5bd5f30880bb88" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "openssl-src" version = "300.1.5+3.1.3" @@ -1641,6 +1710,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "range_map_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8edc89eaa583cf6bc4c6ef16a219f0a60d342ca3bf0eae793560038ac8af1795" + [[package]] name = "rate_limiter" version = "0.1.0" diff --git a/hypervisor/Cargo.toml b/hypervisor/Cargo.toml index bdc4acd14..1149eff18 100644 --- a/hypervisor/Cargo.toml +++ b/hypervisor/Cargo.toml @@ -8,13 +8,14 @@ license = "Apache-2.0 OR BSD-3-Clause" [features] kvm = ["kvm-ioctls", "kvm-bindings", "vfio-ioctls/kvm"] mshv = ["mshv-ioctls", "mshv-bindings", "vfio-ioctls/mshv", "iced-x86"] -sev_snp = [] +sev_snp = ["igvm_parser", "igvm_defs"] tdx = [] [dependencies] anyhow = "1.0.75" byteorder = "1.4.3" -thiserror = "1.0.40" +igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main" , package = "igvm_defs", optional = true } +igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main" , package = "igvm", optional = true } libc = "0.2.147" log = "0.4.17" kvm-ioctls = { version = "0.13.0", optional = true } @@ -26,6 +27,7 @@ serde_with = { version = "3.0.0", default-features = false, features = ["macros" vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic"] } vmm-sys-util = { version = "0.11.0", features = ["with-serde"] } +thiserror = "1.0.40" [target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86] optional = true diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index c07831b43..a7c23306d 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -20,13 +20,21 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use vfio_ioctls::VfioDeviceFd; use vm::DataMatch; + +#[cfg(feature = "sev_snp")] +mod snp_constants; // x86_64 dependencies #[cfg(target_arch = "x86_64")] pub mod x86_64; +#[cfg(feature = "sev_snp")] +use snp_constants::*; + use crate::{ ClockData, CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion, USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, }; +#[cfg(feature = "sev_snp")] +use igvm_defs::IGVM_VHS_SNP_ID_BLOCK; use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] pub use x86_64::VcpuMshvState; @@ -1314,4 +1322,51 @@ impl vm::Vm for MshvVm { .import_isolated_pages(&isolated_pages[0]) .map_err(|e| vm::HypervisorVmError::ImportIsolatedPages(e.into())) } + #[cfg(feature = "sev_snp")] + fn complete_isolated_import( + &self, + snp_id_block: IGVM_VHS_SNP_ID_BLOCK, + host_data: &[u8], + id_block_enabled: u8, + ) -> vm::Result<()> { + let mut auth_info = hv_snp_id_auth_info { + id_key_algorithm: snp_id_block.id_key_algorithm, + auth_key_algorithm: snp_id_block.author_key_algorithm, + ..Default::default() + }; + // Each of r/s component is 576 bits long + auth_info.id_block_signature[..SIG_R_COMPONENT_SIZE_IN_BYTES] + .copy_from_slice(snp_id_block.id_key_signature.r_comp.as_ref()); + auth_info.id_block_signature + [SIG_R_COMPONENT_SIZE_IN_BYTES..SIG_R_AND_S_COMPONENT_SIZE_IN_BYTES] + .copy_from_slice(snp_id_block.id_key_signature.s_comp.as_ref()); + auth_info.id_key[..ECDSA_CURVE_ID_SIZE_IN_BYTES] + .copy_from_slice(snp_id_block.id_public_key.curve.to_le_bytes().as_ref()); + auth_info.id_key[ECDSA_SIG_X_COMPONENT_START..ECDSA_SIG_X_COMPONENT_END] + .copy_from_slice(snp_id_block.id_public_key.qx.as_ref()); + auth_info.id_key[ECDSA_SIG_Y_COMPONENT_START..ECDSA_SIG_Y_COMPONENT_END] + .copy_from_slice(snp_id_block.id_public_key.qy.as_ref()); + + let data = mshv_complete_isolated_import { + import_data: hv_partition_complete_isolated_import_data { + psp_parameters: hv_psp_launch_finish_data { + id_block: hv_snp_id_block { + launch_digest: snp_id_block.ld, + family_id: snp_id_block.family_id, + image_id: snp_id_block.image_id, + version: snp_id_block.version, + guest_svn: snp_id_block.guest_svn, + policy: get_default_snp_guest_policy(), + }, + id_auth_info: auth_info, + host_data: host_data[0..32].try_into().unwrap(), + id_block_enabled, + author_key_enabled: 0, + }, + }, + }; + self.fd + .complete_isolated_import(&data) + .map_err(|e| vm::HypervisorVmError::CompleteIsolatedImport(e.into())) + } } diff --git a/hypervisor/src/mshv/snp_constants.rs b/hypervisor/src/mshv/snp_constants.rs new file mode 100644 index 000000000..84e240c49 --- /dev/null +++ b/hypervisor/src/mshv/snp_constants.rs @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause +// +// Copyright © 2020, Microsoft Corporation +// + +// Reference: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56860.pdf +// Chapter 10 +pub const SIG_R_COMPONENT_SIZE_IN_BYTES: usize = 72; +pub const SIG_R_AND_S_COMPONENT_SIZE_IN_BYTES: usize = 144; +pub const ECDSA_CURVE_ID_SIZE_IN_BYTES: usize = 4; +pub const ECDSA_SIG_X_COMPONENT_SIZE_IN_BYTES: usize = 72; +pub const ECDSA_SIG_Y_COMPONENT_SIZE_IN_BYTES: usize = 72; +pub const ECDSA_SIG_X_COMPONENT_START: usize = ECDSA_CURVE_ID_SIZE_IN_BYTES; +pub const ECDSA_SIG_X_COMPONENT_END: usize = + ECDSA_SIG_X_COMPONENT_START + ECDSA_SIG_X_COMPONENT_SIZE_IN_BYTES; +pub const ECDSA_SIG_Y_COMPONENT_START: usize = ECDSA_SIG_X_COMPONENT_END; +pub const ECDSA_SIG_Y_COMPONENT_END: usize = + ECDSA_SIG_X_COMPONENT_END + ECDSA_SIG_Y_COMPONENT_SIZE_IN_BYTES; diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 9f54430f3..ebe504ede 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -19,6 +19,8 @@ use crate::cpu::Vcpu; use crate::ClockData; use crate::UserMemoryRegion; use crate::{IoEventAddress, IrqRoutingEntry}; +#[cfg(feature = "sev_snp")] +use igvm_defs::IGVM_VHS_SNP_ID_BLOCK; use std::any::Any; #[cfg(target_arch = "x86_64")] use std::fs::File; @@ -225,6 +227,10 @@ pub enum HypervisorVmError { /// #[error("Failed to import isolated pages: {0}")] ImportIsolatedPages(#[source] anyhow::Error), + /// Failed to complete isolated import + /// + #[error("Failed to complete isolated import: {0}")] + CompleteIsolatedImport(#[source] anyhow::Error), } /// /// Result type for returning from a function @@ -374,6 +380,16 @@ pub trait Vm: Send + Sync + Any { ) -> Result<()> { unimplemented!() } + /// Complete the isolated import + #[cfg(feature = "sev_snp")] + fn complete_isolated_import( + &self, + _snp_id_block: IGVM_VHS_SNP_ID_BLOCK, + _host_data: &[u8], + _id_block_enabled: u8, + ) -> Result<()> { + unimplemented!() + } } pub trait VmOps: Send + Sync {