Skip to content

Commit be87033

Browse files
author
Sangho Lee
committed
add support for platform root key
1 parent e174357 commit be87033

7 files changed

Lines changed: 130 additions & 7 deletions

File tree

‎dev_tests/src/ratchet.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ fn ratchet_globals() -> Result<()> {
3636
("dev_bench/", 1),
3737
("litebox/", 9),
3838
("litebox_platform_linux_kernel/", 6),
39-
("litebox_platform_linux_userland/", 5),
40-
("litebox_platform_lvbs/", 23),
39+
("litebox_platform_linux_userland/", 6),
40+
("litebox_platform_lvbs/", 24),
4141
("litebox_platform_multiplex/", 1),
4242
("litebox_platform_windows_userland/", 8),
4343
("litebox_runner_linux_userland/", 1),

‎litebox/src/platform/mod.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,3 +754,40 @@ pub trait CrngProvider {
754754
/// failures.
755755
fn fill_bytes_crng(&self, buf: &mut [u8]);
756756
}
757+
758+
/// A provider of the Platform Root Key (PRK).
759+
///
760+
/// The PRK is a platform-unique secret which can be used to derive secret keys
761+
/// (e.g., TA unique keys, secure storage keys). It serves as the root of trust
762+
/// for cryptographic operations within the trusted or sandboxed execution
763+
/// environment. It resembles the root secret keys provided by trusted hardware
764+
/// devices (e.g., OP-TEE's Hardware Unique Key, DICE's Unique Device Secret,
765+
/// and TPM's Primary Seeds).
766+
///
767+
/// Ideally, the platform should feature a persistent, hardware-backed key (e.g.,
768+
/// fused OTP, PUF-derived). The key should be unique per device, inaccessible
769+
/// outside the trusted environment, and never directly exposed---only used to
770+
/// derive other keys. If the platform lacks such hardware support (e.g., a
771+
/// userland platform), it may generate an ephemeral key from a boot nonce and
772+
/// CRNG, valid only for the current session.
773+
///
774+
/// Note that we do not specify `set_platform_root_key` (yet). This is because
775+
/// each platform has its own way to initialize the PRK (e.g., no initialization
776+
/// if the PRK is baked into hardware, random numbers with different lengths,
777+
/// ...). The platform should initialize the PRK by itself or via the runner.
778+
pub trait PlatformRootKeyProvider {
779+
/// Returns a reference to the Platform Root Key.
780+
///
781+
/// # Errors
782+
///
783+
/// Returns [`PlatformRootKeyError`] if the PRK is not supported or not
784+
/// initialized.
785+
fn platform_root_key(&self) -> Result<&[u8], PlatformRootKeyError> {
786+
Err(PlatformRootKeyError)
787+
}
788+
}
789+
790+
/// Error returned when the platform root key is not supported on the platform.
791+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
792+
#[error("platform root key is not supported on this platform")]
793+
pub struct PlatformRootKeyError;

‎litebox_platform_linux_userland/src/lib.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,6 +2747,43 @@ impl litebox::platform::CrngProvider for LinuxUserland {
27472747
}
27482748
}
27492749

2750+
/// Length of the Platform Root Key in bytes.
2751+
#[cfg(all(target_arch = "x86_64", feature = "optee_syscall"))]
2752+
pub const PRK_LEN: usize = 32;
2753+
2754+
#[cfg(all(target_arch = "x86_64", feature = "optee_syscall"))]
2755+
static PRK_ONCE: std::sync::OnceLock<[u8; PRK_LEN]> = std::sync::OnceLock::new();
2756+
2757+
/// Sets the Platform Root Key (PRK) for this platform.
2758+
///
2759+
/// This should be called once during platform initialization with a key derived
2760+
/// from hardware or a nonce.
2761+
///
2762+
/// # Panics
2763+
/// Panics if `key` length does not match `PRK_LEN`.
2764+
#[cfg(all(target_arch = "x86_64", feature = "optee_syscall"))]
2765+
pub fn set_platform_root_key(key: &[u8]) {
2766+
assert_eq!(key.len(), PRK_LEN, "Platform Root Key length mismatch");
2767+
PRK_ONCE.get_or_init(|| {
2768+
let mut prk = [0u8; PRK_LEN];
2769+
prk.copy_from_slice(key);
2770+
prk
2771+
});
2772+
}
2773+
2774+
#[cfg(all(target_arch = "x86_64", feature = "optee_syscall"))]
2775+
impl litebox::platform::PlatformRootKeyProvider for LinuxUserland {
2776+
fn platform_root_key(&self) -> Result<&[u8], litebox::platform::PlatformRootKeyError> {
2777+
PRK_ONCE
2778+
.get()
2779+
.map(<[u8; PRK_LEN]>::as_slice)
2780+
.ok_or(litebox::platform::PlatformRootKeyError)
2781+
}
2782+
}
2783+
2784+
#[cfg(not(all(target_arch = "x86_64", feature = "optee_syscall")))]
2785+
impl litebox::platform::PlatformRootKeyProvider for LinuxUserland {}
2786+
27502787
/// Dummy `VmapManager`.
27512788
///
27522789
/// In general, userland platforms do not support `vmap` and `vunmap` (which are kernel functions).

‎litebox_platform_lvbs/src/host/lvbs_impl.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,43 @@ impl litebox::platform::CrngProvider for LvbsLinuxKernel {
114114
}
115115
}
116116

117+
/// Length of the Platform Root Key in bytes.
118+
#[cfg(feature = "optee_syscall")]
119+
pub const PRK_LEN: usize = 32;
120+
121+
#[cfg(feature = "optee_syscall")]
122+
static PRK_ONCE: spin::Once<[u8; PRK_LEN]> = spin::Once::new();
123+
124+
/// Sets the Platform Root Key (PRK) for this platform.
125+
///
126+
/// This should be called once during platform initialization with a key derived
127+
/// from hardware or a boot nonce.
128+
///
129+
/// # Panics
130+
/// Panics if `key` length does not match `PRK_LEN`.
131+
#[cfg(feature = "optee_syscall")]
132+
pub fn set_platform_root_key(key: &[u8]) {
133+
assert_eq!(key.len(), PRK_LEN, "Platform Root Key length mismatch");
134+
PRK_ONCE.call_once(|| {
135+
let mut prk = [0u8; PRK_LEN];
136+
prk.copy_from_slice(key);
137+
prk
138+
});
139+
}
140+
141+
#[cfg(feature = "optee_syscall")]
142+
impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel {
143+
fn platform_root_key(&self) -> Result<&[u8], litebox::platform::PlatformRootKeyError> {
144+
PRK_ONCE
145+
.get()
146+
.map(<[u8; PRK_LEN]>::as_slice)
147+
.ok_or(litebox::platform::PlatformRootKeyError)
148+
}
149+
}
150+
151+
#[cfg(not(feature = "optee_syscall"))]
152+
impl litebox::platform::PlatformRootKeyProvider for LvbsLinuxKernel {}
153+
117154
pub struct HostLvbsInterface;
118155

119156
impl HostLvbsInterface {}

‎litebox_platform_lvbs/src/host/mod.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub mod lvbs_impl;
88
pub mod per_cpu_variables;
99

1010
pub use lvbs_impl::LvbsLinuxKernel;
11+
#[cfg(feature = "optee_syscall")]
12+
pub use lvbs_impl::{PRK_LEN, set_platform_root_key};
1113

1214
#[cfg(test)]
1315
pub mod mock;

‎litebox_runner_optee_on_linux_userland/src/lib.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use anyhow::Result;
55
use clap::Parser;
6+
use litebox::platform::CrngProvider;
67
use litebox_common_optee::{TeeUuid, UteeEntryFunc, UteeParamOwned};
78
use litebox_platform_multiplex::Platform;
89
use litebox_shim_optee::session::allocate_session_id;
@@ -98,6 +99,11 @@ pub fn run(cli_args: CliArgs) -> Result<()> {
9899
InterceptionBackend::Rewriter => {}
99100
}
100101

102+
// For now, we use a random PRK for this runner. We can get one via command line if needed.
103+
let mut prk = [0u8; litebox_platform_linux_userland::PRK_LEN];
104+
platform.fill_bytes_crng(&mut prk);
105+
litebox_platform_linux_userland::set_platform_root_key(&prk);
106+
101107
if cli_args.command_sequence.is_empty() {
102108
run_ta_with_default_commands(&shim, ldelf_data.as_slice(), prog_data.as_slice());
103109
} else {

‎litebox_shim_optee/src/syscalls/pta.rs‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use crate::{Task, UserConstPtr, UserMutPtr};
88
use litebox::{
9-
platform::{RawConstPointer as _, RawMutPointer as _},
9+
platform::{PlatformRootKeyProvider, RawConstPointer as _, RawMutPointer as _},
1010
utils::TruncateExt,
1111
};
1212
use litebox_common_optee::{TeeParamType, TeeResult, TeeUuid, UteeParams};
@@ -115,18 +115,22 @@ impl Task {
115115
let output_addr: usize = output.0.truncate();
116116
let output_ptr = UserMutPtr::<u8>::from_usize(output_addr);
117117

118-
// TODO: checks whether output is within the secure memory
119-
120118
// TODO: derive a TA unique key using the hardware unique key (HUK), TA's UUID, and `extra_data`
121119
litebox::log_println!(
122120
self.global.platform,
123121
"derive a key and store it in the secure memory (ptr: {:#x}, size: {})",
124122
output_addr,
125123
output_len
126124
);
127-
// TODO: replace below with a secure key derivation function
125+
let huk = self
126+
.global
127+
.platform
128+
.platform_root_key()
129+
.map_err(|_| TeeResult::NoData)?;
130+
// TODO: the below is a place holder. Replace it with a secure key derivation function (next PR)
128131
let mut key_buf = alloc::vec![0u8; output_len];
129-
self.sys_cryp_random_number_generate(&mut key_buf)?;
132+
let copy_len = core::cmp::min(key_buf.len(), huk.len());
133+
key_buf[..copy_len].copy_from_slice(&huk[..copy_len]);
130134
output_ptr
131135
.copy_from_slice(0, &key_buf)
132136
.ok_or(TeeResult::BadParameters)?;

0 commit comments

Comments
 (0)