From 20c0ddef6139160d707cffd10e8d563f2cc25b54 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Wed, 30 Oct 2024 22:09:43 +0100 Subject: [PATCH] Move serde_extensions module into trussed-core --- Cargo.toml | 5 +- core/Cargo.toml | 2 + core/src/client.rs | 3 +- core/src/lib.rs | 2 + core/src/serde_extensions.rs | 146 +++++++++++++++++++++++++++++++++++ src/serde_extensions.rs | 135 ++------------------------------ 6 files changed, 159 insertions(+), 134 deletions(-) create mode 100644 core/src/serde_extensions.rs diff --git a/Cargo.toml b/Cargo.toml index ae7239ff074..3a346c6deb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ license = "Apache-2.0 OR MIT" heapless = "0.7" heapless-bytes = "0.3" littlefs2-core = { version = "0.1", features = ["serde"] } +postcard = "0.7.0" rand_core = "0.6" serde = { version = "1.0", default-features = false, features = ["derive"] } @@ -39,7 +40,7 @@ generic-array = "0.14.4" heapless = { workspace = true, features = ["serde"] } hex-literal = "0.4.1" nb = "1" -postcard = "0.7.0" +postcard.workspace = true rand_core.workspace = true serde.workspace = true zeroize = { version = "1.2", default-features = false, features = ["zeroize_derive"] } @@ -82,7 +83,7 @@ trussed-derive = { path = "derive" } [features] default = ["default-mechanisms", "default-syscalls", "clients-5"] -serde-extensions = [] +serde-extensions = ["trussed-core/serde-extensions"] std = [] verbose-tests = ["littlefs2/ll-assertions"] verbose-lfs = ["littlefs2/ll-assertions", "littlefs2/ll-trace"] diff --git a/core/Cargo.toml b/core/Cargo.toml index ca07abeaecb..a6bbeccd2a0 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -11,6 +11,7 @@ license.workspace = true heapless.workspace = true heapless-bytes.workspace = true littlefs2-core.workspace = true +postcard.workspace = true rand_core.workspace = true serde.workspace = true @@ -19,3 +20,4 @@ serde-indexed = "0.1" [features] crypto-client-attest = [] counter-client = [] +serde-extensions = [] diff --git a/core/src/client.rs b/core/src/client.rs index 34461da48a7..24bea1b3d42 100644 --- a/core/src/client.rs +++ b/core/src/client.rs @@ -43,8 +43,7 @@ pub struct FutureResult<'c, T, C: ?Sized> where C: PollClient, { - // TODO: make private - pub client: &'c mut C, + pub(crate) client: &'c mut C, __: PhantomData, } diff --git a/core/src/lib.rs b/core/src/lib.rs index d821a8cff3f..213dbc5522a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -11,4 +11,6 @@ pub mod client; pub mod config; pub mod error; pub mod interrupt; +#[cfg(feature = "serde-extensions")] +pub mod serde_extensions; pub mod types; diff --git a/core/src/serde_extensions.rs b/core/src/serde_extensions.rs new file mode 100644 index 00000000000..7c7edd6b021 --- /dev/null +++ b/core/src/serde_extensions.rs @@ -0,0 +1,146 @@ +//! Extensions to the core Trussed syscalls. +//! +//! *Requires the `serde-extensions` feature.* +//! +//! This module makes it possible to add additional syscalls to Trussed by implementing the +//! [`Extension`][] trait. Extension requests and replies are serialized to +//! [`Request::SerdeExtension`][] and [`Reply::SerdeExtension`][]. +//! +//! [`Request::SerdeExtension`]: `crate::api::Request::SerdeExtension` +//! [`Reply::SerdeExtension`]: `crate::api::Reply::SerdeExtension` + +use core::{marker::PhantomData, task::Poll}; + +use serde::{de::DeserializeOwned, Serialize}; + +use crate::{ + api::{reply, request}, + client::{ClientError, FutureResult, PollClient}, + error::Error, + types::Bytes, +}; + +/// A Trussed API extension. +pub trait Extension { + /// The requests supported by this extension. + type Request: DeserializeOwned + Serialize; + /// The replies supported by this extension. + type Reply: DeserializeOwned + Serialize; + + /// Serialize an extension request. + /// + /// Requests that are serialized with this function can be deserialized with + /// [`Extension::deserialize_request`][]. The format is not guaranteed to be stable over + /// crate releases. + #[inline(never)] + fn serialize_request( + id: u8, + request: &Self::Request, + ) -> Result { + postcard::to_vec(request) + .map(Bytes::from) + .map(|request| request::SerdeExtension { id, request }) + .map_err(|_| ClientError::SerializationFailed) + } + + /// Deserialize an extension request. + /// + /// This function can be used to deserialize requests that have been serialized with + /// [`Extension::serialize_request`][]. The format is not guaranteed to be stable over + /// crate releases. + #[inline(never)] + fn deserialize_request(request: &request::SerdeExtension) -> Result { + postcard::from_bytes(&request.request).map_err(|_| Error::InvalidSerializedRequest) + } + + /// Serialize an extension reply. + /// + /// Replies that are serialized with this function can be deserialized with + /// [`Extension::deserialize_reply`][]. The format is not guaranteed to be stable over + /// crate releases. + #[inline(never)] + fn serialize_reply(reply: &Self::Reply) -> Result { + postcard::to_vec(reply) + .map(Bytes::from) + .map(|reply| reply::SerdeExtension { reply }) + .map_err(|_| Error::ReplySerializationFailure) + } + + /// Deserialize an extension reply. + /// + /// This function can be used to deserialize replies that have been serialized with + /// [`Extension::serialize_reply`][]. The format is not guaranteed to be stable over + /// crate releases. + #[inline(never)] + fn deserialize_reply(reply: &reply::SerdeExtension) -> Result { + postcard::from_bytes(&reply.reply).map_err(|_| Error::InvalidSerializedReply) + } +} + +/// Executes extension requests. +/// +/// Instead of using this trait directly, extensions should define their own traits that extend +/// this trait and use the `extension` function to execute extension requests. +pub trait ExtensionClient: PollClient { + /// Returns the ID for the `E` extension as defined by the runner. + fn id() -> u8; + + /// Executes an extension request. + /// + /// Applications should not call this method directly and instead use a trait provided by the + /// extension. + fn extension(&mut self, request: Rq) -> ExtensionResult<'_, E, Rp, Self> + where + Rq: Into, + Rp: TryFrom, + { + let request = E::serialize_request(Self::id(), &request.into())?; + self.request(request).map(From::from) + } +} + +/// A result returned by [`ExtensionClient`][] and clients using it. +pub type ExtensionResult<'a, E, T, C> = Result, ClientError>; + +#[must_use = "Syscalls must be polled with the `syscall` macro"] +/// A future of an [`ExtensionResult`][]. +pub struct ExtensionFutureResult<'c, E, T, C: ?Sized> { + client: &'c mut C, + __: PhantomData<(E, T)>, +} + +impl<'c, E, T, C: ?Sized> ExtensionFutureResult<'c, E, T, C> { + fn new(client: &'c mut C) -> Self { + Self { + client, + __: PhantomData, + } + } +} + +impl<'c, E, T, C> ExtensionFutureResult<'c, E, T, C> +where + E: Extension, + T: TryFrom, + C: PollClient, +{ + pub fn poll(&mut self) -> Poll> { + self.client.poll().map(|result| { + result.and_then(|reply| { + let reply = reply::SerdeExtension::try_from(reply)?; + let reply: E::Reply = E::deserialize_reply(&reply)?; + reply.try_into() + }) + }) + } +} + +impl<'c, E, T, C> From> + for ExtensionFutureResult<'c, E, T, C> +where + C: PollClient + ?Sized, +{ + fn from(result: FutureResult<'c, reply::SerdeExtension, C>) -> Self { + Self::new(result.client) + } +} diff --git a/src/serde_extensions.rs b/src/serde_extensions.rs index 524418f35f6..0789bddaa98 100644 --- a/src/serde_extensions.rs +++ b/src/serde_extensions.rs @@ -13,76 +13,19 @@ //! //! See `tests/serde_extensions.rs` for an example. -use core::{marker::PhantomData, task::Poll}; - use crate::{ api::{reply, request, Reply, Request}, backend::{Backend, CoreOnly, Dispatch, NoId, OptionalBackend}, - client::{ClientError, ClientImplementation, FutureResult, PollClient}, + client::ClientImplementation, error::Error, platform::{Platform, Syscall}, service::ServiceResources, - types::{self, Bytes, Context, CoreContext}, + types::{self, Context, CoreContext}, }; -use serde::{de::DeserializeOwned, Serialize}; - -/// A Trussed API extension. -pub trait Extension { - /// The requests supported by this extension. - type Request: DeserializeOwned + Serialize; - /// The replies supported by this extension. - type Reply: DeserializeOwned + Serialize; - - /// Serialize an extension request. - /// - /// Requests that are serialized with this function can be deserialized with - /// [`Extension::deserialize_request`][]. The format is not guaranteed to be stable over - /// crate releases. - #[inline(never)] - fn serialize_request( - id: u8, - request: &Self::Request, - ) -> Result { - postcard::to_vec(request) - .map(Bytes::from) - .map(|request| request::SerdeExtension { id, request }) - .map_err(|_| ClientError::SerializationFailed) - } - - /// Deserialize an extension request. - /// - /// This function can be used to deserialize requests that have been serialized with - /// [`Extension::serialize_request`][]. The format is not guaranteed to be stable over - /// crate releases. - #[inline(never)] - fn deserialize_request(request: &request::SerdeExtension) -> Result { - postcard::from_bytes(&request.request).map_err(|_| Error::InvalidSerializedRequest) - } - - /// Serialize an extension reply. - /// - /// Replies that are serialized with this function can be deserialized with - /// [`Extension::deserialize_reply`][]. The format is not guaranteed to be stable over - /// crate releases. - #[inline(never)] - fn serialize_reply(reply: &Self::Reply) -> Result { - postcard::to_vec(reply) - .map(Bytes::from) - .map(|reply| reply::SerdeExtension { reply }) - .map_err(|_| Error::ReplySerializationFailure) - } - - /// Deserialize an extension reply. - /// - /// This function can be used to deserialize replies that have been serialized with - /// [`Extension::serialize_reply`][]. The format is not guaranteed to be stable over - /// crate releases. - #[inline(never)] - fn deserialize_reply(reply: &reply::SerdeExtension) -> Result { - postcard::from_bytes(&reply.reply).map_err(|_| Error::InvalidSerializedReply) - } -} +pub use trussed_core::serde_extensions::{ + Extension, ExtensionClient, ExtensionFutureResult, ExtensionResult, +}; /// Dispatches extension requests to custom backends. pub trait ExtensionDispatch { @@ -198,28 +141,6 @@ pub trait ExtensionId { const ID: Self::Id; } -/// Executes extension requests. -/// -/// Instead of using this trait directly, extensions should define their own traits that extend -/// this trait and use the `extension` function to execute extension requests. -pub trait ExtensionClient: PollClient { - /// Returns the ID for the `E` extension as defined by the runner, see [`ExtensionId`][]. - fn id() -> u8; - - /// Executes an extension request. - /// - /// Applications should not call this method directly and instead use a trait provided by the - /// extension. - fn extension(&mut self, request: Rq) -> ExtensionResult<'_, E, Rp, Self> - where - Rq: Into, - Rp: TryFrom, - { - let request = E::serialize_request(Self::id(), &request.into())?; - self.request(request).map(From::from) - } -} - impl ExtensionClient for ClientImplementation where E: Extension, @@ -230,49 +151,3 @@ where I::ID.into() } } - -/// A result returned by [`ExtensionClient`][] and clients using it. -pub type ExtensionResult<'a, E, T, C> = Result, ClientError>; - -#[must_use = "Syscalls must be polled with the `syscall` macro"] -/// A future of an [`ExtensionResult`][]. -pub struct ExtensionFutureResult<'c, E, T, C: ?Sized> { - client: &'c mut C, - __: PhantomData<(E, T)>, -} - -impl<'c, E, T, C: ?Sized> ExtensionFutureResult<'c, E, T, C> { - fn new(client: &'c mut C) -> Self { - Self { - client, - __: PhantomData, - } - } -} - -impl<'c, E, T, C> ExtensionFutureResult<'c, E, T, C> -where - E: Extension, - T: TryFrom, - C: PollClient, -{ - pub fn poll(&mut self) -> Poll> { - self.client.poll().map(|result| { - result.and_then(|reply| { - let reply = reply::SerdeExtension::try_from(reply)?; - let reply: E::Reply = E::deserialize_reply(&reply)?; - reply.try_into() - }) - }) - } -} - -impl<'c, E, T, C> From> - for ExtensionFutureResult<'c, E, T, C> -where - C: PollClient + ?Sized, -{ - fn from(result: FutureResult<'c, reply::SerdeExtension, C>) -> Self { - Self::new(result.client) - } -}