diff --git a/apps/system/components/SDKRuntime/SDKRuntime.camkes b/apps/system/components/SDKRuntime/SDKRuntime.camkes index facd82f..b2ac3dc 100644 --- a/apps/system/components/SDKRuntime/SDKRuntime.camkes +++ b/apps/system/components/SDKRuntime/SDKRuntime.camkes @@ -17,6 +17,7 @@ import ; import ; import ; +import ; component SDKRuntime { provides SDKManagerInterface sdk_manager; @@ -24,6 +25,7 @@ component SDKRuntime { maybe uses LoggerInterface logger; uses MemoryInterface memory; + uses SecurityCoordinatorInterface security; // Enable KataOS CAmkES support. attribute int kataos = true; diff --git a/apps/system/components/SDKRuntime/kata-sdk-component/src/run.rs b/apps/system/components/SDKRuntime/kata-sdk-component/src/run.rs index 728a219..a4f33b2 100644 --- a/apps/system/components/SDKRuntime/kata-sdk-component/src/run.rs +++ b/apps/system/components/SDKRuntime/kata-sdk-component/src/run.rs @@ -40,9 +40,11 @@ use kata_os_common::camkes::{seL4_CPath, Camkes}; use kata_os_common::copyregion::CopyRegion; use kata_os_common::cspace_slot::CSpaceSlot; use kata_os_common::sel4_sys; +use kata_sdk_interface::KeyValueData; use kata_sdk_interface::SDKAppId; use kata_sdk_interface::SDKError; use kata_sdk_interface::SDKReplyHeader; +use kata_sdk_interface::SDKRuntimeError; use kata_sdk_interface::SDKRuntimeInterface; use kata_sdk_interface::SDKRuntimeRequest; use kata_sdk_interface::SDKRUNTIME_REQUEST_DATA_SIZE; @@ -185,6 +187,15 @@ pub unsafe extern "C" fn run() -> ! { if let Err(status) = match header.request { SDKRuntimeRequest::Ping => ping_request(app_id, args_slice, reply_slice), SDKRuntimeRequest::Log => log_request(app_id, args_slice, reply_slice), + SDKRuntimeRequest::ReadKey => { + read_key_request(app_id, args_slice, reply_slice) + } + SDKRuntimeRequest::WriteKey => { + write_key_request(app_id, args_slice, reply_slice) + } + SDKRuntimeRequest::DeleteKey => { + delete_key_request(app_id, args_slice, reply_slice) + } } { reply_error(status, reply_slice); } @@ -207,6 +218,10 @@ pub unsafe extern "C" fn run() -> ! { // SDK RPC request handling: unmarshal request, dispatch to KATA_SDK, // and marshal reply. +fn serialize_failure(e: postcard::Error) -> SDKError { + error!("serialize failed: {:?}", e); + SDKError::SerializeFailed +} fn deserialize_failure(e: postcard::Error) -> SDKError { error!("deserialize failed: {:?}", e); SDKError::DeserializeFailed @@ -231,6 +246,50 @@ fn log_request( unsafe { KATA_SDK.log(app_id, msg) } } +fn read_key_request( + app_id: SDKAppId, + request_slice: &[u8], + reply_slice: &mut [u8], +) -> Result<(), SDKError> { + let request = postcard::from_bytes::(request_slice) + .map_err(deserialize_failure)?; + #[allow(clippy::uninit_assumed_init)] + let mut keyval: KeyValueData = unsafe { ::core::mem::MaybeUninit::uninit().assume_init() }; + let value = unsafe { KATA_SDK.read_key(app_id, request.key, &mut keyval)? }; + let _ = postcard::to_slice( + &kata_sdk_interface::ReadKeyResponse { + header: SDKReplyHeader::new(SDKRuntimeError::SDKSuccess), + value, + }, + reply_slice, + ) + .map_err(serialize_failure)?; + Ok(()) +} + +fn write_key_request( + app_id: SDKAppId, + request_slice: &[u8], + _reply_slice: &mut [u8], +) -> Result<(), SDKError> { + let request = postcard::from_bytes::(request_slice) + .map_err(deserialize_failure)?; + // NB: the serialized data are variable length so copy to convert + let mut keyval = [0u8; kata_sdk_interface::KEY_VALUE_DATA_SIZE]; + keyval[..request.value.len()].copy_from_slice(request.value); + unsafe { KATA_SDK.write_key(app_id, request.key, &keyval) } +} + +fn delete_key_request( + app_id: SDKAppId, + request_slice: &[u8], + _reply_slice: &mut [u8], +) -> Result<(), SDKError> { + let request = postcard::from_bytes::(request_slice) + .map_err(deserialize_failure)?; + unsafe { KATA_SDK.delete_key(app_id, request.key) } +} + // SDKManager RPC handling; these arrive via CAmkES so have a C linkage. #[no_mangle] diff --git a/apps/system/components/SDKRuntime/kata-sdk-interface/src/lib.rs b/apps/system/components/SDKRuntime/kata-sdk-interface/src/lib.rs index 35c1ef9..c9c5048 100644 --- a/apps/system/components/SDKRuntime/kata-sdk-interface/src/lib.rs +++ b/apps/system/components/SDKRuntime/kata-sdk-interface/src/lib.rs @@ -58,6 +58,11 @@ pub const SDKRUNTIME_REQUEST_DATA_SIZE: usize = PAGE_SIZE / 2; /// on 64-bit platforms these are 64-bits. pub type SDKAppId = usize; +// TODO(sleffler): temp constraint on value part of key-value pairs +// TOOD(sleffler): dup's security coordinator but we don't want a dependency +pub const KEY_VALUE_DATA_SIZE: usize = 100; +pub type KeyValueData = [u8; KEY_VALUE_DATA_SIZE]; + /// All RPC request must have an SDKRequestHeader at the front. #[derive(Serialize, Deserialize)] pub struct SDKRequestHeader { @@ -95,11 +100,39 @@ pub struct LogRequest<'a> { pub msg: &'a [u8], } +/// SDKRuntimeRequest::ReadKey +#[derive(Serialize, Deserialize)] +pub struct ReadKeyRequest<'a> { + pub key: &'a str, +} +#[derive(Serialize, Deserialize)] +pub struct ReadKeyResponse<'a> { + pub header: SDKReplyHeader, + pub value: &'a [u8], +} + +/// SDKRuntimeRequest::WriteKey +#[derive(Serialize, Deserialize)] +pub struct WriteKeyRequest<'a> { + pub key: &'a str, + pub value: &'a [u8], +} + +/// SDKRuntimeRequest::DeleteKey +#[derive(Serialize, Deserialize)] +pub struct DeleteKeyRequest<'a> { + pub key: &'a str, +} + #[repr(C)] // XXX needed? #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] pub enum SDKRuntimeRequest { Ping = 0, // Check runtime is alive Log, // Log message: [msg: &str] + + ReadKey, // Read key: [key: &str, &mut [u8]] -> value: &[u8] + WriteKey, // Write key: [key: &str, value: &KeyValueData] + DeleteKey, // Delete key: [key: &str] } /// Rust interface for the SDKRuntime. @@ -119,6 +152,21 @@ pub trait SDKRuntimeInterface { /// Logs |msg| through the system logger. fn log(&self, app_id: SDKAppId, msg: &str) -> Result<(), SDKError>; + + /// Returns any value for the specified |key| in the app's private key-value store. + /// Data are written to |keyval| and returned as a slice. + fn read_key<'a>( + &self, + app_id: SDKAppId, + key: &str, + keyval: &'a mut [u8], + ) -> Result<&'a [u8], SDKError>; + + /// Writes |value| for the specified |key| in the app's private key-value store. + fn write_key(&self, app_id: SDKAppId, key: &str, value: &KeyValueData) -> Result<(), SDKError>; + + /// Deletes the specified |key| in the app's private key-value store. + fn delete_key(&self, app_id: SDKAppId, key: &str) -> Result<(), SDKError>; } /// Rust client-side request processing. Note there is no CAmkES stub to @@ -195,3 +243,44 @@ pub fn kata_sdk_log(msg: &str) -> Result<(), SDKRuntimeError> { )?; header.into() } + +/// Rust client-side wrapper for the read key method. +// TODO(sleffler): _mut variant? +#[inline] +#[allow(dead_code)] +pub fn kata_sdk_read_key<'a>(key: &str, keyval: &'a mut [u8]) -> Result<&'a [u8], SDKRuntimeError> { + let response = kata_sdk_request::( + SDKRuntimeRequest::ReadKey, + &ReadKeyRequest { key }, + )?; + match response.header.status { + SDKRuntimeError::SDKSuccess => { + let (left, _) = keyval.split_at_mut(response.value.len()); + left.copy_from_slice(response.value); + Ok(left) + } + e => Err(e), + } +} + +/// Rust client-side wrapper for the write key method. +#[inline] +#[allow(dead_code)] +pub fn kata_sdk_write_key(key: &str, value: &[u8]) -> Result<(), SDKRuntimeError> { + let header = kata_sdk_request::( + SDKRuntimeRequest::WriteKey, + &WriteKeyRequest { key, value }, + )?; + header.into() +} + +/// Rust client-side wrapper for the delete key method. +#[inline] +#[allow(dead_code)] +pub fn kata_sdk_delete_key(key: &str) -> Result<(), SDKRuntimeError> { + let header = kata_sdk_request::( + SDKRuntimeRequest::DeleteKey, + &DeleteKeyRequest { key }, + )?; + header.into() +} diff --git a/apps/system/components/SDKRuntime/kata-sdk-runtime/Cargo.toml b/apps/system/components/SDKRuntime/kata-sdk-runtime/Cargo.toml index a165d19..2b41eba 100644 --- a/apps/system/components/SDKRuntime/kata-sdk-runtime/Cargo.toml +++ b/apps/system/components/SDKRuntime/kata-sdk-runtime/Cargo.toml @@ -20,6 +20,7 @@ edition = "2021" [dependencies] hashbrown = { version = "0.11", features = ["ahash-compile-time-rng"] } kata-os-common = { path = "../../kata-os-common" } +kata-security-interface = { path = "../../SecurityCoordinator/kata-security-interface" } kata-sdk-interface = { path = "../kata-sdk-interface" } kata-sdk-manager = { path = "../kata-sdk-manager" } log = { version = "0.4", features = ["release_max_level_info"] } diff --git a/apps/system/components/SDKRuntime/kata-sdk-runtime/src/lib.rs b/apps/system/components/SDKRuntime/kata-sdk-runtime/src/lib.rs index a6409cf..0529216 100644 --- a/apps/system/components/SDKRuntime/kata-sdk-runtime/src/lib.rs +++ b/apps/system/components/SDKRuntime/kata-sdk-runtime/src/lib.rs @@ -18,6 +18,7 @@ use kata_os_common::camkes::seL4_CPath; use kata_os_common::sel4_sys; use kata_sdk_interface::error::SDKError; +use kata_sdk_interface::KeyValueData; use kata_sdk_interface::SDKAppId; use kata_sdk_interface::SDKRuntimeInterface; use kata_sdk_manager::SDKManagerError; @@ -69,4 +70,30 @@ impl SDKRuntimeInterface for KataSDKRuntime { fn log(&self, app_id: SDKAppId, msg: &str) -> Result<(), SDKError> { self.runtime.lock().as_ref().unwrap().log(app_id, msg) } + fn read_key<'a>( + &self, + app_id: SDKAppId, + key: &str, + keyval: &'a mut [u8], + ) -> Result<&'a [u8], SDKError> { + self.runtime + .lock() + .as_ref() + .unwrap() + .read_key(app_id, key, keyval) + } + fn write_key(&self, app_id: SDKAppId, key: &str, value: &KeyValueData) -> Result<(), SDKError> { + self.runtime + .lock() + .as_ref() + .unwrap() + .write_key(app_id, key, value) + } + fn delete_key(&self, app_id: SDKAppId, key: &str) -> Result<(), SDKError> { + self.runtime + .lock() + .as_ref() + .unwrap() + .delete_key(app_id, key) + } } diff --git a/apps/system/components/SDKRuntime/kata-sdk-runtime/src/runtime/mod.rs b/apps/system/components/SDKRuntime/kata-sdk-runtime/src/runtime/mod.rs index ec6b59c..812a226 100644 --- a/apps/system/components/SDKRuntime/kata-sdk-runtime/src/runtime/mod.rs +++ b/apps/system/components/SDKRuntime/kata-sdk-runtime/src/runtime/mod.rs @@ -18,10 +18,14 @@ use kata_os_common::camkes::seL4_CPath; use kata_os_common::cspace_slot::CSpaceSlot; use kata_os_common::sel4_sys; use kata_sdk_interface::error::SDKError; +use kata_sdk_interface::KeyValueData; use kata_sdk_interface::SDKAppId; use kata_sdk_interface::SDKRuntimeInterface; use kata_sdk_manager::SDKManagerError; use kata_sdk_manager::SDKManagerInterface; +use kata_security_interface::kata_security_delete_key; +use kata_security_interface::kata_security_read_key; +use kata_security_interface::kata_security_write_key; use log::{error, info}; use smallstr::SmallString; @@ -147,4 +151,44 @@ impl SDKRuntimeInterface for SDKRuntime { None => Err(SDKError::InvalidBadge), } } + + /// Returns any value for the specified |key| in the app's private key-value store. + fn read_key<'a>( + &self, + app_id: SDKAppId, + key: &str, + keyval: &'a mut [u8], + ) -> Result<&'a [u8], SDKError> { + match self.apps.get(&app_id) { + Some(app) => { + kata_security_read_key(&app.id, key, keyval) + .map_err(|_| SDKError::ReadKeyFailed)?; // XXX + Ok(keyval) + } + None => Err(SDKError::InvalidBadge), + } + } + + /// Writes |value| for the specified |key| in the app's private key-value store. + fn write_key(&self, app_id: SDKAppId, key: &str, value: &KeyValueData) -> Result<(), SDKError> { + match self.apps.get(&app_id) { + Some(app) => { + kata_security_write_key(&app.id, key, value) + .map_err(|_| SDKError::WriteKeyFailed)?; // XXX + Ok(()) + } + None => Err(SDKError::InvalidBadge), + } + } + + /// Deletes the specified |key| in the app's private key-value store. + fn delete_key(&self, app_id: SDKAppId, key: &str) -> Result<(), SDKError> { + match self.apps.get(&app_id) { + Some(app) => { + kata_security_delete_key(&app.id, key).map_err(|_| SDKError::DeleteKeyFailed)?; // XXX + Ok(()) + } + None => Err(SDKError::InvalidBadge), + } + } } diff --git a/apps/system/system.camkes b/apps/system/system.camkes index f561691..d7296a2 100644 --- a/apps/system/system.camkes +++ b/apps/system/system.camkes @@ -173,6 +173,7 @@ assembly { from debug_console.security, // NB: for debug/test from process_manager.security, from ml_coordinator.security, // NB: for LoadModel + from sdk_runtime.security, // NB: for key-value store to security_coordinator.security); // Connect the DebugConsole to the OpenTitanUARTDriver.