Skip to content

Commit

Permalink
Rework errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Norbert Fabritius committed Sep 13, 2023
1 parent 9430bf7 commit 3562504
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 92 deletions.
21 changes: 21 additions & 0 deletions examples/linux/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/linux/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ path = "src/main.rs"

[dependencies]
embassy-executor = { version = "0.2", features = ["arch-std", "executor-thread", "integrated-timers", "log", "nightly"] }
embassy-sync = { version = "0.2", default-features = false }
embassy-time = { version = "0.1", features = ["log", "std"] }
heapless = "0.7"
hex = "0.4"
Expand Down
55 changes: 34 additions & 21 deletions examples/linux/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
#![feature(type_alias_impl_trait)] // Required for embassy

use core::iter::Enumerate;
use embassy_executor::Spawner;
use embassy_time::Duration;
use embassy_time::{Duration, queue};
use embassy_time::Timer;
use heapless::spsc::{Consumer, Producer, Queue};
use heimlig::client::api::Api;
use heimlig::client::api::RequestSink;
use heimlig::common::jobs::{Request, Response};
use heimlig::crypto::rng;
use heimlig::crypto::rng::Rng;
use heimlig::hsm::core::Core;
use heimlig::hsm::core::ResponseSink;
use heimlig::hsm::keystore::NoKeyStore;
use embassy_sync::mutex::Mutex;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use heimlig::common::queues;
use heimlig::common::queues::{RequestSink, ResponseSink};
use log::{error, info};
use rand::RngCore;

Expand All @@ -28,43 +32,43 @@ impl rng::EntropySource for EntropySource {
data
}
}
struct RequestQueueSink<'ch, 'a> {
producer: Producer<'ch, Request<'a>, QUEUE_SIZE>,
struct RequestQueueSink<'ch, 'data> {
producer: Producer<'ch, Request<'data>, QUEUE_SIZE>,
}

impl<'a> RequestSink<'a> for RequestQueueSink<'_, 'a> {
fn send(&mut self, request: Request<'a>) -> Result<(), heimlig::client::api::Error> {
impl<'data> RequestSink<'data> for RequestQueueSink<'_, 'data> {
fn send(&mut self, request: Request<'data>) -> Result<(), queues::Error> {
self.producer
.enqueue(request)
.map_err(|_| heimlig::client::api::Error::QueueFull)
.map_err(|_| queues::Error::Enqueue)
}

fn ready(&self) -> bool {
self.producer.ready()
}
}

struct RequestQueueSource<'ch, 'a> {
consumer: Consumer<'ch, Request<'a>, QUEUE_SIZE>,
struct RequestQueueSource<'ch, 'data> {
consumer: Consumer<'ch, Request<'data>, QUEUE_SIZE>,
}

impl<'a> Iterator for RequestQueueSource<'_, 'a> {
type Item = Request<'a>;
impl<'data> Iterator for RequestQueueSource<'_, 'data> {
type Item = Request<'data>;

fn next(&mut self) -> Option<Self::Item> {
self.consumer.dequeue()
}
}

struct ResponseQueueSink<'ch, 'a> {
producer: Producer<'ch, Response<'a>, QUEUE_SIZE>,
struct ResponseQueueSink<'ch, 'data> {
producer: Producer<'ch, Response<'data>, QUEUE_SIZE>,
}

impl<'a> ResponseSink<'a> for ResponseQueueSink<'_, 'a> {
fn send(&mut self, response: Response<'a>) -> Result<(), heimlig::hsm::core::Error> {
impl<'data> ResponseSink<'data> for ResponseQueueSink<'_, 'data> {
fn send(&mut self, response: Response<'data>) -> Result<(), queues::Error> {
self.producer
.enqueue(response)
.map_err(|_| heimlig::hsm::core::Error::QueueFull)
.map_err(|_| queues::Error::Enqueue)
}
fn ready(&self) -> bool {
self.producer.ready()
Expand Down Expand Up @@ -93,12 +97,21 @@ async fn hsm_task(
let responses_sink = ResponseQueueSink { producer: resp_tx };

let rng = Rng::new(EntropySource {}, None);
let mut core = Core::new_without_key_store(rng, requests_source.enumerate(), responses_sink);

loop {
let key_store = NoKeyStore{};
let key_store = Mutex::<NoopRawMutex, NoKeyStore>::new(key_store);
let mut core: Core<
NoopRawMutex,
NoKeyStore,
Enumerate<RequestQueueSource<'_, '_>>,
ResponseQueueSink<'_,'_>,
RequestQueueSink<'_, '_>,
Enumerate<ResponseQueueSource<'_, '_>>,
> = Core::new(&key_store, requests_source.enumerate(), responses_sink);

/*loop {
core.process_next().expect("failed to process next request");
Timer::after(Duration::from_millis(100)).await;
}
}*/
}

#[embassy_executor::task]
Expand Down
37 changes: 19 additions & 18 deletions heimlig/src/client/api.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
use crate::common::jobs::{Request, Response};

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Error {
/// Attempted to push to a full queue.
QueueFull,
}

/// Sink where the requests to the Core can be pushed to
pub trait RequestSink<'a> {
/// Send a [Request] to the client through this sink.
fn send(&mut self, request: Request<'a>) -> Result<(), Error>;
fn ready(&self) -> bool;
}
use crate::common::queues;
use crate::common::queues::RequestSink;

/// An interface to send [Request]s to the HSM core and receive [Response]es from it.
pub struct Api<'a, Req: RequestSink<'a>, Resp: Iterator<Item = Response<'a>>> {
requests_sink: Req,
responses_source: Resp,
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Error {
SinkNotReady,
Send(queues::Error),
}

impl<'a, Req: RequestSink<'a>, Resp: Iterator<Item = Response<'a>>> Api<'a, Req, Resp> {
/// Create a new instance of the HSM API.
pub fn new(requests_sink: Req, responses_source: Resp) -> Self {
Expand All @@ -31,10 +26,13 @@ impl<'a, Req: RequestSink<'a>, Resp: Iterator<Item = Response<'a>>> Api<'a, Req,
/// Request `size` many random bytes.
pub fn get_random(&mut self, output: &'a mut [u8]) -> Result<(), Error> {
if self.requests_sink.ready() {
self.requests_sink.send(Request::GetRandom { output })
self.requests_sink
.send(Request::GetRandom { output })
.map_err(Error::Send)?
} else {
Err(Error::QueueFull)
Err(Error::SinkNotReady)?
}
Ok(())
}

/// Attempt to poll a response and return it.
Expand All @@ -45,8 +43,9 @@ impl<'a, Req: RequestSink<'a>, Resp: Iterator<Item = Response<'a>>> Api<'a, Req,

#[cfg(test)]
mod test {
use crate::client::api::{Api, Error, RequestSink};
use crate::client::api::{Api, RequestSink};
use crate::common::jobs::{Request, Response};
use crate::common::queues;
use heapless::spsc::{Consumer, Producer, Queue};

const QUEUE_SIZE: usize = 8;
Expand All @@ -56,8 +55,10 @@ mod test {
}

impl<'a> RequestSink<'a> for RequestQueueSink<'_, 'a> {
fn send(&mut self, request: Request<'a>) -> Result<(), Error> {
self.producer.enqueue(request).map_err(|_| Error::QueueFull)
fn send(&mut self, request: Request<'a>) -> Result<(), queues::Error> {
self.producer
.enqueue(request)
.map_err(|_| queues::Error::Enqueue)
}

fn ready(&self) -> bool {
Expand Down
1 change: 1 addition & 0 deletions heimlig/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod jobs;
pub mod limits;
pub mod queues;
27 changes: 27 additions & 0 deletions heimlig/src/common/queues.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::common::jobs::{Request, Response};

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Error {
/// No [Channel] found for given ID.
UnknownChannelId,
/// Attempted to push to a full queue.
QueueFull,
/// Failed to enqueue into a queue
Enqueue,
/// Sink was not ready
NotReady,
}

/// Sink where the responses from the Core can be pushed to
pub trait ResponseSink<'data> {
/// Send a [Response] to the client through this sink.
fn send(&mut self, response: Response<'data>) -> Result<(), Error>;
fn ready(&self) -> bool;
}

/// Sink where the requests to the Core can be pushed to
pub trait RequestSink<'data> {
/// Send a [Request] to the client through this sink.
fn send(&mut self, request: Request<'data>) -> Result<(), Error>;
fn ready(&self) -> bool;
}
36 changes: 8 additions & 28 deletions heimlig/src/hsm/core.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::common::jobs;
use crate::common::jobs::{Request, RequestType, Response};
use crate::common::queues::{Error, RequestSink, ResponseSink};
use crate::hsm::keystore::KeyStore;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
Expand Down Expand Up @@ -28,26 +29,6 @@ pub struct Core<
>,
}

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Error {
/// No [Channel] found for given ID.
UnknownChannelId,
/// Attempted to push to a full queue.
QueueFull,
}

/// Sink where the responses from the Core can be pushed to
pub trait ResponseSink<'data> {
/// Send a [Response] to the client through this sink.
fn send(&mut self, response: Response<'data>) -> Result<(), Error>;
fn ready(&self) -> bool;
}

pub trait RequestSink<'data> {
fn send(&mut self, request: Request<'data>) -> Result<(), Error>;
fn ready(&self) -> bool;
}

/// Associate request types with worker channels
struct ReqTypesToWorkerQueues<
'data,
Expand Down Expand Up @@ -163,15 +144,14 @@ impl<
/// * `Ok(false)` if no [Request] was found in any input [Channel].
/// * `Err(core::Error)` if a processing error occurred.
pub fn process_client_requests(&mut self) -> Result<(), Error> {
if self.client_responses.ready() {
let request = self.client_requests.next();
if let Some((request_id, request)) = request {
return self.process(request_id, request);
}
Ok(()) // Nothing to process
} else {
Err(Error::QueueFull)
if !self.client_responses.ready() {
return Err(Error::NotReady);
}
let request = self.client_requests.next();
if let Some((request_id, request)) = request {
return self.process(request_id, request);
}
Ok(()) // Nothing to process
}

// TODO: Move request ID into Request struct
Expand Down
7 changes: 4 additions & 3 deletions heimlig/src/hsm/workers/chachapoly_worker.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::common::jobs::{Error, Request, Response};
use crate::common::queues;
use crate::common::queues::ResponseSink;
use crate::config::keystore::MAX_KEY_SIZE;
use crate::hsm::core::ResponseSink;
use crate::hsm::keystore::KeyStore;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
Expand Down Expand Up @@ -29,7 +30,7 @@ impl<
> ChaChaPolyWorker<'data, 'keystore, M, K, ReqSrc, RespSink>
{
// TODO: Do not use core errors here? Export errors in trait as typedef?
pub fn execute(&mut self) -> Result<(), crate::hsm::core::Error> {
pub fn execute(&mut self) -> Result<(), queues::Error> {
if self.responses.ready() {
let mut key_buffer = Zeroizing::new([0u8; MAX_KEY_SIZE]);
let response = match self.requests.next() {
Expand Down Expand Up @@ -96,7 +97,7 @@ impl<
self.responses.send(response)?;
Ok(())
} else {
Err(crate::hsm::core::Error::QueueFull)
Err(queues::Error::QueueFull)
}
}
pub fn encrypt_external_key<'a>(
Expand Down
7 changes: 4 additions & 3 deletions heimlig/src/hsm/workers/rng_worker.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::common::jobs::Response::GetRandom;
use crate::common::jobs::{Error, Request, Response};
use crate::common::limits::MAX_RANDOM_SIZE;
use crate::common::queues;
use crate::common::queues::ResponseSink;
use crate::crypto::rng::{EntropySource, Rng};
use crate::hsm::core::ResponseSink;
use rand_core::RngCore;

pub struct RngWorker<
Expand All @@ -24,7 +25,7 @@ impl<
> RngWorker<'data, E, ReqSrc, RespSink>
{
// TODO: Do not use core errors here? Export errors in trait as typedef?
pub fn execute(&mut self) -> Result<(), crate::hsm::core::Error> {
pub fn execute(&mut self) -> Result<(), queues::Error> {
if self.responses.ready() {
match self.requests.next() {
Some((_id, Request::GetRandom { output })) => {
Expand All @@ -37,7 +38,7 @@ impl<
}
Ok(()) // Nothing to process
} else {
Err(crate::hsm::core::Error::QueueFull)
Err(queues::Error::QueueFull)
}
}

Expand Down
Loading

0 comments on commit 3562504

Please sign in to comment.