Skip to content

Commit

Permalink
Add derive macros for Dispatch, ExtensionDispatch
Browse files Browse the repository at this point in the history
This patch adds a new derive crate that can be used to derive
implementations of the trussed::backend::Dispatch and
trussed::serde_extensions::ExtensionDispatch traits.
  • Loading branch information
robin-nitrokey committed Mar 24, 2024
1 parent 8b52bca commit 79764af
Show file tree
Hide file tree
Showing 14 changed files with 704 additions and 123 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,26 @@ jobs:
release: "9-2020-q2"

- name: Build
run: cargo build --verbose --target ${{ matrix.target }}
run: cargo build --workspace --target ${{ matrix.target }}

- name: Check all targets without default features
run: cargo check --all-targets --no-default-features
run: cargo check --workspace --all-targets --no-default-features
if: matrix.target == 'x86_64-unknown-linux-gnu'

- name: Check all targets with default features
run: cargo check --all-targets
run: cargo check --workspace --all-targets
if: matrix.target == 'x86_64-unknown-linux-gnu'

- name: Check all features and targets
run: cargo check --all-features --all-targets
run: cargo check --workspace --all-features --all-targets
if: matrix.target == 'x86_64-unknown-linux-gnu'

- name: Run tests
run: cargo test --verbose --features serde-extensions,virt
run: cargo test --features serde-extensions,virt
if: matrix.target == 'x86_64-unknown-linux-gnu'

- name: Check formatting
run: cargo fmt -- --check
run: cargo fmt --all -- --check
if: matrix.target == 'x86_64-unknown-linux-gnu'

- name: Check clippy lints
Expand Down
19 changes: 15 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
[workspace]
members = ["derive"]

[workspace.package]
authors = ["Nicolas Stalder <n@stalder.io>", "Nitrokey GmbH"]
edition = "2021"
homepage = "https://trussed.dev"
license = "Apache-2.0 OR MIT"

[package]
name = "trussed"
version = "0.1.0"
authors = ["Nicolas Stalder <n@stalder.io>"]
edition = "2021"
homepage = "https://trussed.dev"
repository = "https://github.com/trussed-dev/trussed"
license = "Apache-2.0 OR MIT"
description = "Modern Cryptographic Firmware"
readme = "README.md"

authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true

[dependencies]
# general
bitflags = { version = "2.1" }
Expand Down Expand Up @@ -56,6 +66,7 @@ once_cell = "1.13.0"
serde_test = "1"
# If this is not enabled, serde_test makes serde_cbor's compilation fail
serde_cbor = { version = "0.11.2", features = ["std"] }
trussed-derive = { path = "derive" }
# Somehow, this is causing a regression.
# rand_core = { version = "0.5", features = ["getrandom"] }

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
clippy:
cargo clippy --all-features --all-targets -- --deny warnings
cargo clippy --workspace --all-features --all-targets -- --deny warnings

quick-test:
cargo test -- --nocapture
Expand Down
20 changes: 20 additions & 0 deletions derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "trussed-derive"
version = "0.1.0"

authors.workspace = true
edition.workspace = true
homepage.workspace = true
license.workspace = true

[lib]
proc-macro = true

[dev-dependencies]
serde = { version = "1.0", default-features = false }
trussed = { path = "..", features = ["serde-extensions", "virt"] }

[dependencies]
proc-macro2 = "1.0.51"
quote = "1.0.23"
syn = "2.0.53"
49 changes: 49 additions & 0 deletions derive/examples/dispatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
mod backends {
use trussed::backend::Backend;

#[derive(Default)]
pub struct ABackend;

impl Backend for ABackend {
type Context = ();
}
}

enum Backend {
A,
}

#[derive(Default, trussed_derive::Dispatch)]
#[dispatch(backend_id = "Backend")]
struct Dispatch {
a: backends::ABackend,
}

fn main() {
use trussed::{
backend::BackendId,
client::CryptoClient,
try_syscall,
virt::{self, Ram},
Error,
};

fn run(backends: &'static [BackendId<Backend>], expected: Option<Error>) {
virt::with_platform(Ram::default(), |platform| {
platform.run_client_with_backends(
"test",
Dispatch::default(),
backends,
|mut client| {
assert_eq!(try_syscall!(client.random_bytes(42)).err(), expected);
},
)
});
}

run(&[BackendId::Core], None);
run(
&[BackendId::Custom(Backend::A)],
Some(Error::RequestNotAvailable),
);
}
143 changes: 143 additions & 0 deletions derive/examples/extension-dispatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use trussed::Error;

mod backends {
use super::extensions::{TestExtension, TestReply, TestRequest};
use trussed::{
backend::Backend, platform::Platform, serde_extensions::ExtensionImpl,
service::ServiceResources, types::CoreContext, Error,
};

#[derive(Default)]
pub struct ABackend;

impl Backend for ABackend {
type Context = ();
}

impl ExtensionImpl<TestExtension> for ABackend {
fn extension_request<P: Platform>(
&mut self,
_core_ctx: &mut CoreContext,
_backend_ctx: &mut Self::Context,
_request: &TestRequest,
_resources: &mut ServiceResources<P>,
) -> Result<TestReply, Error> {
Ok(TestReply)
}
}
}

mod extensions {
use serde::{Deserialize, Serialize};
use trussed::{
serde_extensions::{Extension, ExtensionClient, ExtensionResult},
Error,
};

pub struct TestExtension;

impl Extension for TestExtension {
type Request = TestRequest;
type Reply = TestReply;
}

#[derive(Deserialize, Serialize)]
pub struct TestRequest;

#[derive(Deserialize, Serialize)]
pub struct TestReply;

impl TryFrom<TestReply> for () {
type Error = Error;

fn try_from(_reply: TestReply) -> Result<Self, Self::Error> {
Ok(())
}
}

pub trait TestClient {
fn test(&mut self) -> ExtensionResult<'_, TestExtension, (), Self>;
}

impl<C: ExtensionClient<TestExtension>> TestClient for C {
fn test(&mut self) -> ExtensionResult<'_, TestExtension, (), Self> {
self.extension(TestRequest)
}
}

pub struct SampleExtension;

impl Extension for SampleExtension {
type Request = SampleRequest;
type Reply = SampleReply;
}

#[derive(Deserialize, Serialize)]
pub struct SampleRequest;

#[derive(Deserialize, Serialize)]
pub struct SampleReply;
}

enum Backend {
A,
}

enum Extension {
Test = 0,
Sample = 1,
}

impl From<Extension> for u8 {
fn from(extension: Extension) -> u8 {
extension as u8
}
}

impl TryFrom<u8> for Extension {
type Error = Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::Test),
1 => Ok(Self::Sample),
_ => Err(Error::InternalError),
}
}
}

#[derive(Default, trussed_derive::ExtensionDispatch)]
#[dispatch(backend_id = "Backend", extension_id = "Extension")]
#[extensions(
Test = "extensions::TestExtension",
Sample = "extensions::SampleExtension"
)]
struct Dispatch {
#[extensions("Test")]
a: backends::ABackend,
}

fn main() {
use extensions::TestClient;
use trussed::{
backend::BackendId,
try_syscall,
virt::{self, Ram},
};

fn run(backends: &'static [BackendId<Backend>], expected: Option<Error>) {
virt::with_platform(Ram::default(), |platform| {
platform.run_client_with_backends(
"test",
Dispatch::default(),
backends,
|mut client| {
assert_eq!(try_syscall!(client.test()).err(), expected);
},
)
});
}

run(&[BackendId::Core], Some(Error::RequestNotAvailable));
run(&[BackendId::Custom(Backend::A)], None);
}
Loading

0 comments on commit 79764af

Please sign in to comment.