diff --git a/dev_tests/src/ratchet.rs b/dev_tests/src/ratchet.rs index 61e3137e8..254b29d9c 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_linux_userland/", 1), diff --git a/litebox_platform_lvbs/src/host/lvbs_impl.rs b/litebox_platform_lvbs/src/host/lvbs_impl.rs index 8bb1f415b..e678fe111 100644 --- a/litebox_platform_lvbs/src/host/lvbs_impl.rs +++ b/litebox_platform_lvbs/src/host/lvbs_impl.rs @@ -114,6 +114,27 @@ impl litebox::platform::CrngProvider for LvbsLinuxKernel { } } +/// Length of the Platform Root Key in bytes. +pub 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 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 = [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..0ac8271fa 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 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..ebcd09368 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 @@ -152,6 +152,9 @@ pub enum VsmError { #[error("symbol name contains invalid UTF-8")] SymbolNameInvalidUtf8, + + #[error("root key is invalid")] + PlatformRootKeyInvalid, } impl From for VsmError { @@ -217,7 +220,8 @@ impl From for Errno { | VsmError::SymbolNameInvalidUtf8 | VsmError::SymbolNameNoTerminator | VsmError::CertificateDerLengthInvalid { .. } - | VsmError::CertificateParseFailed => Errno::EINVAL, + | VsmError::CertificateParseFailed + | VsmError::PlatformRootKeyInvalid => Errno::EINVAL, // Signature verification failures delegate to VerificationError's Errno mapping VsmError::SignatureVerificationFailed(e) => Errno::from(e), diff --git a/litebox_platform_lvbs/src/mshv/mod.rs b/litebox_platform_lvbs/src/mshv/mod.rs index 0da18875d..c250fc748 100644 --- a/litebox_platform_lvbs/src/mshv/mod.rs +++ b/litebox_platform_lvbs/src/mshv/mod.rs @@ -130,6 +130,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; @@ -152,6 +155,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 483de17bb..d06609446 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, @@ -916,6 +918,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 = [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 { @@ -939,6 +963,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 8a20135d8..e097fb4ad 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::log_println!( self.global.platform,