diff --git a/Cargo.lock b/Cargo.lock index ad0c763ca..e43cffa1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1572,6 +1572,7 @@ dependencies = [ "x509-cert", "x86_64", "zerocopy", + "zeroize", ] [[package]] diff --git a/dev_tests/src/ratchet.rs b/dev_tests/src/ratchet.rs index 339967240..d5b76f069 100644 --- a/dev_tests/src/ratchet.rs +++ b/dev_tests/src/ratchet.rs @@ -37,7 +37,7 @@ fn ratchet_globals() -> Result<()> { ("litebox/", 9), ("litebox_platform_linux_kernel/", 6), ("litebox_platform_linux_userland/", 5), - ("litebox_platform_lvbs/", 23), + ("litebox_platform_lvbs/", 24), ("litebox_platform_multiplex/", 1), ("litebox_platform_windows_userland/", 8), ("litebox_runner_lvbs/", 6), diff --git a/litebox_platform_lvbs/Cargo.toml b/litebox_platform_lvbs/Cargo.toml index 992dc508e..0c628a346 100644 --- a/litebox_platform_lvbs/Cargo.toml +++ b/litebox_platform_lvbs/Cargo.toml @@ -32,6 +32,7 @@ digest = { version = "0.10.7", default-features = false } aligned-vec = { version = "0.6.4", default-features = false } raw-cpuid = "11.6.0" zerocopy = { version = "0.8", default-features = false, features = ["derive"] } +zeroize = { version = "1.8", default-features = false } [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = { version = "0.15.2", default-features = false, features = ["instructions"] } diff --git a/litebox_platform_lvbs/src/host/lvbs_impl.rs b/litebox_platform_lvbs/src/host/lvbs_impl.rs index 8bb1f415b..977461a69 100644 --- a/litebox_platform_lvbs/src/host/lvbs_impl.rs +++ b/litebox_platform_lvbs/src/host/lvbs_impl.rs @@ -7,6 +7,7 @@ use crate::{ Errno, HostInterface, arch::ioport::serial_print_string, host::per_cpu_variables::with_per_cpu_variables, }; +use zeroize::Zeroizing; pub type LvbsLinuxKernel = crate::LinuxKernel; @@ -114,6 +115,27 @@ impl litebox::platform::CrngProvider for LvbsLinuxKernel { } } +/// Length of the Platform Root Key in bytes. +pub(crate) const PRK_LEN: usize = 32; + +static PRK_ONCE: spin::Once<[u8; PRK_LEN]> = spin::Once::new(); + +/// Sets the Platform Root Key (PRK) for this platform. +/// +/// This should be called once during platform initialization with a key derived +/// from hardware or a boot nonce. +/// +/// # Panics +/// Panics if `key` length does not match `PRK_LEN`. +pub(crate) fn set_platform_root_key(key: &[u8]) { + assert_eq!(key.len(), PRK_LEN, "Platform Root Key length mismatch"); + PRK_ONCE.call_once(|| { + let mut prk = Zeroizing::new([0u8; PRK_LEN]); + prk.copy_from_slice(key); + *prk + }); +} + pub struct HostLvbsInterface; impl HostLvbsInterface {} diff --git a/litebox_platform_lvbs/src/host/mod.rs b/litebox_platform_lvbs/src/host/mod.rs index 48fa248e8..197836bc7 100644 --- a/litebox_platform_lvbs/src/host/mod.rs +++ b/litebox_platform_lvbs/src/host/mod.rs @@ -8,6 +8,7 @@ pub mod lvbs_impl; pub mod per_cpu_variables; pub use lvbs_impl::LvbsLinuxKernel; +pub(crate) use lvbs_impl::{PRK_LEN, set_platform_root_key}; #[cfg(test)] pub mod mock; diff --git a/litebox_platform_lvbs/src/mshv/error.rs b/litebox_platform_lvbs/src/mshv/error.rs index 5d6274be5..aa767b78f 100644 --- a/litebox_platform_lvbs/src/mshv/error.rs +++ b/litebox_platform_lvbs/src/mshv/error.rs @@ -106,7 +106,7 @@ pub enum VsmError { OperationNotSupported(&'static str), // VTL0 Memory Copy Errors - #[error("failed to copy data to VTL0")] + #[error("failed to copy data from/to VTL0")] Vtl0CopyFailed, // Hypercall Errors diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 12f8a5207..826daaa39 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -128,6 +128,9 @@ pub const VSM_VTL_CALL_FUNC_ID_KEXEC_VALIDATE: u32 = 0x1_ffea; pub const VSM_VTL_CALL_FUNC_ID_PATCH_TEXT: u32 = 0x1_ffeb; pub const VSM_VTL_CALL_FUNC_ID_ALLOCATE_RINGBUFFER_MEMORY: u32 = 0x1_ffec; +// This VSM function ID for setting the platform root key is subject to change +pub const VSM_VTL_CALL_FUNC_ID_SET_PLATFORM_ROOT_KEY: u32 = 0x1_ffed; + // This VSM function ID for OP-TEE messages is subject to change pub const VSM_VTL_CALL_FUNC_ID_OPTEE_MESSAGE: u32 = 0x1_fff0; @@ -150,6 +153,7 @@ pub enum VsmFunction { PatchText = VSM_VTL_CALL_FUNC_ID_PATCH_TEXT, OpteeMessage = VSM_VTL_CALL_FUNC_ID_OPTEE_MESSAGE, AllocateRingbufferMemory = VSM_VTL_CALL_FUNC_ID_ALLOCATE_RINGBUFFER_MEMORY, + SetPlatformRootKey = VSM_VTL_CALL_FUNC_ID_SET_PLATFORM_ROOT_KEY, } pub const MSR_EFER: u32 = 0xc000_0080; diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index f66989fa3..9470d0add 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -9,9 +9,11 @@ use crate::mshv::ringbuffer::set_ringbuffer; use crate::{ debug_serial_println, host::{ + PRK_LEN, bootparam::get_vtl1_memory_info, linux::{CpuMask, KEXEC_SEGMENT_MAX, Kimage}, per_cpu_variables::with_per_cpu_variables, + set_platform_root_key, }, mshv::{ HV_REGISTER_CR_INTERCEPT_CONTROL, HV_REGISTER_CR_INTERCEPT_CR0_MASK, @@ -56,6 +58,7 @@ use x86_64::{ }; use x509_cert::{Certificate, der::Decode}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; +use zeroize::Zeroizing; #[derive(Copy, Clone, FromBytes, Immutable, KnownLayout)] #[repr(align(4096))] @@ -894,6 +897,28 @@ fn mshv_vsm_allocate_ringbuffer_memory(phys_addr: u64, size: usize) -> Result Result { + if crate::platform_low().vtl0_kernel_info.check_end_of_boot() { + return Err(VsmError::OperationAfterEndOfBoot("set platform root key")); + } + + let key_pa = PhysAddr::try_new(key_pa).map_err(|_| VsmError::InvalidPhysicalAddress)?; + + let mut keybuf = Zeroizing::new([0u8; PRK_LEN]); + if unsafe { crate::platform_low().copy_slice_from_vtl0_phys(key_pa, &mut *keybuf) } { + set_platform_root_key(&*keybuf); + Ok(0) + } else { + Err(VsmError::Vtl0CopyFailed) + } +} + /// VSM function dispatcher pub fn vsm_dispatch(func_id: VsmFunction, params: &[u64]) -> i64 { let result: Result = match func_id { @@ -917,6 +942,7 @@ pub fn vsm_dispatch(func_id: VsmFunction, params: &[u64]) -> i64 { let size: usize = params[1].truncate(); mshv_vsm_allocate_ringbuffer_memory(params[0], size) } + VsmFunction::SetPlatformRootKey => mshv_vsm_set_platform_root_key(params[0]), VsmFunction::OpteeMessage => Err(VsmError::OperationNotSupported("OP-TEE communication")), }; match result { diff --git a/litebox_shim_optee/src/syscalls/pta.rs b/litebox_shim_optee/src/syscalls/pta.rs index 0c1000b47..a8be183d1 100644 --- a/litebox_shim_optee/src/syscalls/pta.rs +++ b/litebox_shim_optee/src/syscalls/pta.rs @@ -115,8 +115,6 @@ impl Task { let output_addr: usize = output.0.truncate(); let output_ptr = UserMutPtr::::from_usize(output_addr); - // TODO: checks whether output is within the secure memory - // TODO: derive a TA unique key using the hardware unique key (HUK), TA's UUID, and `extra_data` litebox_util_log::debug!( ptr:% = format_args!("{:#x}", output_addr),