SDKRuntime: add key-val store api's

Change-Id: Ic25986719bdea04adc989f2ea5d2cedd664017d7
GitOrigin-RevId: 738e0e63de82ec0bda91e1982d32e0922a181184
This commit is contained in:
Sam Leffler 2022-09-19 23:18:22 +00:00
parent fae20dcd68
commit 8b7c33c565
7 changed files with 223 additions and 0 deletions

View File

@ -17,6 +17,7 @@
import <LoggerInterface.camkes>;
import <MemoryInterface.camkes>;
import <SDKManagerInterface.camkes>;
import <SecurityCoordinatorInterface.camkes>;
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;

View File

@ -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::<kata_sdk_interface::ReadKeyRequest>(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::<kata_sdk_interface::WriteKeyRequest>(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::<kata_sdk_interface::DeleteKeyRequest>(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]

View File

@ -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::<ReadKeyRequest, ReadKeyResponse>(
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::<WriteKeyRequest, SDKReplyHeader>(
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::<DeleteKeyRequest, SDKReplyHeader>(
SDKRuntimeRequest::DeleteKey,
&DeleteKeyRequest { key },
)?;
header.into()
}

View File

@ -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"] }

View File

@ -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)
}
}

View File

@ -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),
}
}
}

View File

@ -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.