From a4f42dfb5347cdaf4d6fe9ce5caaf30223e7978a Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Tue, 14 Apr 2026 18:02:46 +0000 Subject: [PATCH 1/6] add support for platform root key --- dev_tests/src/ratchet.rs | 4 +- litebox_platform_lvbs/src/host/lvbs_impl.rs | 37 +++++++++++++++++++ litebox_platform_lvbs/src/host/mod.rs | 2 + .../src/lib.rs | 6 +++ litebox_shim_optee/src/syscalls/pta.rs | 14 ++++--- 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/dev_tests/src/ratchet.rs b/dev_tests/src/ratchet.rs index 61e3137e8..d092c3562 100644 --- a/dev_tests/src/ratchet.rs +++ b/dev_tests/src/ratchet.rs @@ -36,8 +36,8 @@ fn ratchet_globals() -> Result<()> { ("dev_bench/", 1), ("litebox/", 9), ("litebox_platform_linux_kernel/", 6), - ("litebox_platform_linux_userland/", 5), - ("litebox_platform_lvbs/", 23), + ("litebox_platform_linux_userland/", 6), + ("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..d0be9b534 100644 --- a/litebox_platform_lvbs/src/host/lvbs_impl.rs +++ b/litebox_platform_lvbs/src/host/lvbs_impl.rs @@ -114,6 +114,43 @@ impl litebox::platform::CrngProvider for LvbsLinuxKernel { } } +/// Length of the Platform Root Key in bytes. +#[cfg(feature = "optee_syscall")] +pub const PRK_LEN: usize = 32; + +#[cfg(feature = "optee_syscall")] +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`. +#[cfg(feature = "optee_syscall")] +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 + }); +} + +#[cfg(feature = "optee_syscall")] +impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel { + fn platform_root_key(&self) -> Result<&[u8], litebox::platform::PlatformRootKeyError> { + PRK_ONCE + .get() + .map(<[u8; PRK_LEN]>::as_slice) + .ok_or(litebox::platform::PlatformRootKeyError) + } +} + +#[cfg(not(feature = "optee_syscall"))] +impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel {} + 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..ecf266380 100644 --- a/litebox_platform_lvbs/src/host/mod.rs +++ b/litebox_platform_lvbs/src/host/mod.rs @@ -8,6 +8,8 @@ pub mod lvbs_impl; pub mod per_cpu_variables; pub use lvbs_impl::LvbsLinuxKernel; +#[cfg(feature = "optee_syscall")] +pub use lvbs_impl::{PRK_LEN, set_platform_root_key}; #[cfg(test)] pub mod mock; diff --git a/litebox_runner_optee_on_linux_userland/src/lib.rs b/litebox_runner_optee_on_linux_userland/src/lib.rs index 1c5547225..7597d4e54 100644 --- a/litebox_runner_optee_on_linux_userland/src/lib.rs +++ b/litebox_runner_optee_on_linux_userland/src/lib.rs @@ -3,6 +3,7 @@ use anyhow::Result; use clap::Parser; +use litebox::platform::CrngProvider; use litebox_common_optee::{TeeUuid, UteeEntryFunc, UteeParamOwned}; use litebox_platform_multiplex::Platform; use litebox_shim_optee::session::allocate_session_id; @@ -108,6 +109,11 @@ pub fn run(cli_args: CliArgs) -> Result<()> { InterceptionBackend::Rewriter => {} } + // For now, we use a random PRK for this runner. We can get one via command line if needed. + let mut prk = [0u8; litebox_platform_linux_userland::PRK_LEN]; + platform.fill_bytes_crng(&mut prk); + litebox_platform_linux_userland::set_platform_root_key(&prk); + if cli_args.command_sequence.is_empty() { run_ta_with_default_commands(&shim, ldelf_data.as_slice(), prog_data.as_slice()); } else { diff --git a/litebox_shim_optee/src/syscalls/pta.rs b/litebox_shim_optee/src/syscalls/pta.rs index 8a20135d8..8e100c808 100644 --- a/litebox_shim_optee/src/syscalls/pta.rs +++ b/litebox_shim_optee/src/syscalls/pta.rs @@ -6,7 +6,7 @@ use crate::{Task, UserConstPtr, UserMutPtr}; use litebox::{ - platform::{RawConstPointer as _, RawMutPointer as _}, + platform::{PlatformRootKeyProvider, RawConstPointer as _, RawMutPointer as _}, utils::TruncateExt, }; use litebox_common_optee::{TeeParamType, TeeResult, TeeUuid, UteeParams}; @@ -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, @@ -124,9 +122,15 @@ impl Task { output_addr, output_len ); - // TODO: replace below with a secure key derivation function + let huk = self + .global + .platform + .platform_root_key() + .map_err(|_| TeeResult::NoData)?; + // TODO: the below is a place holder. Replace it with a secure key derivation function (next PR) let mut key_buf = alloc::vec![0u8; output_len]; - self.sys_cryp_random_number_generate(&mut key_buf)?; + let copy_len = core::cmp::min(key_buf.len(), huk.len()); + key_buf[..copy_len].copy_from_slice(&huk[..copy_len]); output_ptr .copy_from_slice(0, &key_buf) .ok_or(TeeResult::BadParameters)?; From d0e3e4a44d6bda5e029086c332c68b3d6cf3eca3 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Wed, 15 Apr 2026 15:36:16 +0000 Subject: [PATCH 2/6] set_platform_root_key for LVBS --- litebox_platform_lvbs/src/mshv/error.rs | 8 +++++-- litebox_platform_lvbs/src/mshv/mod.rs | 4 ++++ litebox_platform_lvbs/src/mshv/vsm.rs | 31 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) 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..326bbb834 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,34 @@ 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 key_size: usize = key_size.truncate(); + if key_size != PRK_LEN { + return Err(VsmError::PlatformRootKeyInvalid); + } + + 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 +969,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], params[1]), VsmFunction::OpteeMessage => Err(VsmError::OperationNotSupported("OP-TEE communication")), }; match result { From d5d235a8975f426afcf83228a288b1d15efc3856 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Thu, 16 Apr 2026 23:31:30 +0000 Subject: [PATCH 3/6] drop PlatformRootKeyProvider --- litebox_platform_lvbs/src/host/lvbs_impl.rs | 13 ------------- litebox_runner_optee_on_linux_userland/src/lib.rs | 6 ------ litebox_shim_optee/src/syscalls/pta.rs | 11 ++--------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/litebox_platform_lvbs/src/host/lvbs_impl.rs b/litebox_platform_lvbs/src/host/lvbs_impl.rs index d0be9b534..553591ac7 100644 --- a/litebox_platform_lvbs/src/host/lvbs_impl.rs +++ b/litebox_platform_lvbs/src/host/lvbs_impl.rs @@ -138,19 +138,6 @@ pub fn set_platform_root_key(key: &[u8]) { }); } -#[cfg(feature = "optee_syscall")] -impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel { - fn platform_root_key(&self) -> Result<&[u8], litebox::platform::PlatformRootKeyError> { - PRK_ONCE - .get() - .map(<[u8; PRK_LEN]>::as_slice) - .ok_or(litebox::platform::PlatformRootKeyError) - } -} - -#[cfg(not(feature = "optee_syscall"))] -impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel {} - pub struct HostLvbsInterface; impl HostLvbsInterface {} diff --git a/litebox_runner_optee_on_linux_userland/src/lib.rs b/litebox_runner_optee_on_linux_userland/src/lib.rs index 7597d4e54..1c5547225 100644 --- a/litebox_runner_optee_on_linux_userland/src/lib.rs +++ b/litebox_runner_optee_on_linux_userland/src/lib.rs @@ -3,7 +3,6 @@ use anyhow::Result; use clap::Parser; -use litebox::platform::CrngProvider; use litebox_common_optee::{TeeUuid, UteeEntryFunc, UteeParamOwned}; use litebox_platform_multiplex::Platform; use litebox_shim_optee::session::allocate_session_id; @@ -109,11 +108,6 @@ pub fn run(cli_args: CliArgs) -> Result<()> { InterceptionBackend::Rewriter => {} } - // For now, we use a random PRK for this runner. We can get one via command line if needed. - let mut prk = [0u8; litebox_platform_linux_userland::PRK_LEN]; - platform.fill_bytes_crng(&mut prk); - litebox_platform_linux_userland::set_platform_root_key(&prk); - if cli_args.command_sequence.is_empty() { run_ta_with_default_commands(&shim, ldelf_data.as_slice(), prog_data.as_slice()); } else { diff --git a/litebox_shim_optee/src/syscalls/pta.rs b/litebox_shim_optee/src/syscalls/pta.rs index 8e100c808..f5e2354e9 100644 --- a/litebox_shim_optee/src/syscalls/pta.rs +++ b/litebox_shim_optee/src/syscalls/pta.rs @@ -6,7 +6,7 @@ use crate::{Task, UserConstPtr, UserMutPtr}; use litebox::{ - platform::{PlatformRootKeyProvider, RawConstPointer as _, RawMutPointer as _}, + platform::{RawConstPointer as _, RawMutPointer as _}, utils::TruncateExt, }; use litebox_common_optee::{TeeParamType, TeeResult, TeeUuid, UteeParams}; @@ -122,15 +122,8 @@ impl Task { output_addr, output_len ); - let huk = self - .global - .platform - .platform_root_key() - .map_err(|_| TeeResult::NoData)?; - // TODO: the below is a place holder. Replace it with a secure key derivation function (next PR) let mut key_buf = alloc::vec![0u8; output_len]; - let copy_len = core::cmp::min(key_buf.len(), huk.len()); - key_buf[..copy_len].copy_from_slice(&huk[..copy_len]); + self.sys_cryp_random_number_generate(&mut key_buf)?; output_ptr .copy_from_slice(0, &key_buf) .ok_or(TeeResult::BadParameters)?; From 6583abdc9cd5dcf4283b8f1adcdcf1f6ef400195 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Thu, 16 Apr 2026 23:39:54 +0000 Subject: [PATCH 4/6] ratchet and minor fix --- dev_tests/src/ratchet.rs | 2 +- litebox_shim_optee/src/syscalls/pta.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dev_tests/src/ratchet.rs b/dev_tests/src/ratchet.rs index d092c3562..254b29d9c 100644 --- a/dev_tests/src/ratchet.rs +++ b/dev_tests/src/ratchet.rs @@ -36,7 +36,7 @@ fn ratchet_globals() -> Result<()> { ("dev_bench/", 1), ("litebox/", 9), ("litebox_platform_linux_kernel/", 6), - ("litebox_platform_linux_userland/", 6), + ("litebox_platform_linux_userland/", 5), ("litebox_platform_lvbs/", 24), ("litebox_platform_multiplex/", 1), ("litebox_platform_windows_userland/", 8), diff --git a/litebox_shim_optee/src/syscalls/pta.rs b/litebox_shim_optee/src/syscalls/pta.rs index f5e2354e9..e097fb4ad 100644 --- a/litebox_shim_optee/src/syscalls/pta.rs +++ b/litebox_shim_optee/src/syscalls/pta.rs @@ -122,6 +122,7 @@ impl Task { output_addr, output_len ); + // TODO: replace below with a secure key derivation function let mut key_buf = alloc::vec![0u8; output_len]; self.sys_cryp_random_number_generate(&mut key_buf)?; output_ptr From a9fa4a8c690a95acf27d811e0a185877997afa1b Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Fri, 17 Apr 2026 02:03:15 +0000 Subject: [PATCH 5/6] make root key universal --- litebox_platform_lvbs/src/host/lvbs_impl.rs | 3 --- litebox_platform_lvbs/src/host/mod.rs | 1 - 2 files changed, 4 deletions(-) diff --git a/litebox_platform_lvbs/src/host/lvbs_impl.rs b/litebox_platform_lvbs/src/host/lvbs_impl.rs index 553591ac7..e678fe111 100644 --- a/litebox_platform_lvbs/src/host/lvbs_impl.rs +++ b/litebox_platform_lvbs/src/host/lvbs_impl.rs @@ -115,10 +115,8 @@ impl litebox::platform::CrngProvider for LvbsLinuxKernel { } /// Length of the Platform Root Key in bytes. -#[cfg(feature = "optee_syscall")] pub const PRK_LEN: usize = 32; -#[cfg(feature = "optee_syscall")] static PRK_ONCE: spin::Once<[u8; PRK_LEN]> = spin::Once::new(); /// Sets the Platform Root Key (PRK) for this platform. @@ -128,7 +126,6 @@ static PRK_ONCE: spin::Once<[u8; PRK_LEN]> = spin::Once::new(); /// /// # Panics /// Panics if `key` length does not match `PRK_LEN`. -#[cfg(feature = "optee_syscall")] pub fn set_platform_root_key(key: &[u8]) { assert_eq!(key.len(), PRK_LEN, "Platform Root Key length mismatch"); PRK_ONCE.call_once(|| { diff --git a/litebox_platform_lvbs/src/host/mod.rs b/litebox_platform_lvbs/src/host/mod.rs index ecf266380..0ac8271fa 100644 --- a/litebox_platform_lvbs/src/host/mod.rs +++ b/litebox_platform_lvbs/src/host/mod.rs @@ -8,7 +8,6 @@ pub mod lvbs_impl; pub mod per_cpu_variables; pub use lvbs_impl::LvbsLinuxKernel; -#[cfg(feature = "optee_syscall")] pub use lvbs_impl::{PRK_LEN, set_platform_root_key}; #[cfg(test)] From b4125152ecc7e7729e3e1b438b223f149bb331c1 Mon Sep 17 00:00:00 2001 From: Sangho Lee Date: Tue, 21 Apr 2026 21:53:51 +0000 Subject: [PATCH 6/6] revise mshv_vsm_set_platform_root_key signature --- litebox_platform_lvbs/src/mshv/vsm.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index 326bbb834..d06609446 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -920,22 +920,16 @@ fn mshv_vsm_allocate_ringbuffer_memory(phys_addr: u64, size: usize) -> Result Result { +/// This function assumes that the caller stores key bytes in a single or +/// contiguous physical memory page(s), whose length is equal to `PRK_LEN`. +fn mshv_vsm_set_platform_root_key(key_pa: u64) -> 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 key_size: usize = key_size.truncate(); - if key_size != PRK_LEN { - return Err(VsmError::PlatformRootKeyInvalid); - } let mut keybuf = [0u8; PRK_LEN]; if unsafe { crate::platform_low().copy_slice_from_vtl0_phys(key_pa, &mut keybuf) } { @@ -969,7 +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], params[1]), + VsmFunction::SetPlatformRootKey => mshv_vsm_set_platform_root_key(params[0]), VsmFunction::OpteeMessage => Err(VsmError::OperationNotSupported("OP-TEE communication")), }; match result {