diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..1feac7f20ea --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Run cargo fmt +2eb064a8ce147cd32b6697c0d24330789a57c7ac diff --git a/src/api.rs b/src/api.rs index 6278a35b03d..2a32a51c833 100644 --- a/src/api.rs +++ b/src/api.rs @@ -5,9 +5,9 @@ //! [pkcs11-v3]: https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/pkcs11-base-v3.0.html //! [pkcs11-headers]: https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/cs01/include/pkcs11-v3.0/ +use crate::types::*; use core::hint::unreachable_unchecked; use core::time::Duration; -use crate::types::*; #[macro_use] mod macros; @@ -44,7 +44,7 @@ generate_enums! { ReadDirFilesFirst: 13 ReadDirFilesNext: 14 ReadFile: 15 - Metadata: 26 + Metadata: 26 // ReadCounter: 7 RandomBytes: 16 SerializeKey: 17 @@ -360,7 +360,7 @@ pub mod reply { DebugDumpStore: - Decrypt: + Decrypt: - plaintext: Option Delete: @@ -379,7 +379,7 @@ pub mod reply { DeserializeKey: - key: KeyId - Encrypt: + Encrypt: - ciphertext: Message - nonce: ShortData - tag: ShortData @@ -482,5 +482,4 @@ pub mod reply { WriteCertificate: - id: CertId } - } diff --git a/src/api/macros.rs b/src/api/macros.rs index 34d275e41e3..9e3ef24cb41 100644 --- a/src/api/macros.rs +++ b/src/api/macros.rs @@ -100,4 +100,3 @@ macro_rules! impl_reply { )*} } - diff --git a/src/client.rs b/src/client.rs index 539677a4b1f..599d468d6be 100644 --- a/src/client.rs +++ b/src/client.rs @@ -101,40 +101,48 @@ pub enum ClientError { pub type ClientResult<'c, T, C> = core::result::Result, ClientError>; /// All-in-one trait bounding on the sub-traits. -pub trait Client: CertificateClient + CryptoClient + CounterClient + FilesystemClient + ManagementClient + UiClient {} +pub trait Client: + CertificateClient + CryptoClient + CounterClient + FilesystemClient + ManagementClient + UiClient +{ +} impl Client for ClientImplementation {} /// Lowest level interface, use one of the higher level ones. pub trait PollClient { - fn request>(&mut self, req: impl Into) -> ClientResult<'_, T, Self>; + fn request>( + &mut self, + req: impl Into, + ) -> ClientResult<'_, T, Self>; fn poll(&mut self) -> core::task::Poll>; fn syscall(&mut self); } pub struct FutureResult<'c, T, C: ?Sized> -where C: PollClient +where + C: PollClient, { client: &'c mut C, __: PhantomData, } -impl<'c,T, C> FutureResult<'c, T, C> +impl<'c, T, C> FutureResult<'c, T, C> where T: From, C: PollClient, { pub fn new(client: &'c mut C) -> Self { - Self { client, __: PhantomData} + Self { + client, + __: PhantomData, + } } - pub fn poll(&mut self) - -> core::task::Poll> - { + pub fn poll(&mut self) -> core::task::Poll> { use core::task::Poll::{Pending, Ready}; match self.client.poll() { Ready(Ok(reply)) => Ready(Ok(T::from(reply))), Ready(Err(error)) => Ready(Err(error)), - Pending => Pending + Pending => Pending, } } } @@ -159,20 +167,23 @@ pub struct ClientImplementation { // } impl ClientImplementation -where S: Syscall +where + S: Syscall, { pub fn new(interchange: Requester, syscall: S) -> Self { - Self { interchange, pending: None, syscall } + Self { + interchange, + pending: None, + syscall, + } } - } impl PollClient for ClientImplementation -where S: Syscall { - - fn poll(&mut self) - -> core::task::Poll> - { +where + S: Syscall, +{ + fn poll(&mut self) -> core::task::Poll> { match self.interchange.take_response() { Some(reply) => { // #[cfg(all(test, feature = "verbose-tests"))] @@ -182,9 +193,13 @@ where S: Syscall { if Some(u8::from(&reply)) == self.pending { self.pending = None; core::task::Poll::Ready(Ok(reply)) - } else { + } else { // #[cfg(all(test, feature = "verbose-tests"))] - info!("got: {:?}, expected: {:?}", Some(u8::from(&reply)), self.pending); + info!( + "got: {:?}, expected: {:?}", + Some(u8::from(&reply)), + self.pending + ); core::task::Poll::Ready(Err(Error::InternalError)) } } @@ -193,17 +208,16 @@ where S: Syscall { core::task::Poll::Ready(Err(error)) } } - - }, - None => core::task::Poll::Pending + } + None => core::task::Poll::Pending, } } // call with any of `crate::api::request::*` - fn request>(&mut self, req: impl Into) - // -> core::result::Result>, ClientError> - -> ClientResult<'_, T, Self> - { + fn request>( + &mut self, + req: impl Into, + ) -> ClientResult<'_, T, Self> { // TODO: handle failure // TODO: fail on pending (non-canceled) request) if self.pending.is_some() { @@ -234,18 +248,16 @@ impl UiClient for ClientImplementation {} /// Read/Write + Delete certificates pub trait CertificateClient: PollClient { - - fn delete_certificate(&mut self, id: CertId) - -> ClientResult<'_, reply::DeleteCertificate, Self> - { + fn delete_certificate( + &mut self, + id: CertId, + ) -> ClientResult<'_, reply::DeleteCertificate, Self> { let r = self.request(request::DeleteCertificate { id })?; r.client.syscall(); Ok(r) } - fn read_certificate(&mut self, id: CertId) - -> ClientResult<'_, reply::ReadCertificate, Self> - { + fn read_certificate(&mut self, id: CertId) -> ClientResult<'_, reply::ReadCertificate, Self> { let r = self.request(request::ReadCertificate { id })?; r.client.syscall(); Ok(r) @@ -255,30 +267,31 @@ pub trait CertificateClient: PollClient { /// as-is. It might make sense to add attributes (such as "deletable"). /// (On the other hand, the attn CA certs are not directly accessible to clients, /// and generated attn certs can be regenerated). - fn write_certificate(&mut self, location: Location, der: &[u8]) - -> ClientResult<'_, reply::WriteCertificate, Self> - { + fn write_certificate( + &mut self, + location: Location, + der: &[u8], + ) -> ClientResult<'_, reply::WriteCertificate, Self> { let der = Message::from_slice(der).map_err(|_| ClientError::DataTooLarge)?; let r = self.request(request::WriteCertificate { location, der })?; r.client.syscall(); Ok(r) } - } /// Trussed Client interface that Trussed apps can rely on. pub trait CryptoClient: PollClient { // call with any of `crate::api::request::*` // fn request<'c>(&'c mut self, req: impl Into) - // -> core::result::Result, ClientError>; + // -> core::result::Result, ClientError>; fn agree( - &mut self, mechanism: Mechanism, - private_key: KeyId, public_key: KeyId, + &mut self, + mechanism: Mechanism, + private_key: KeyId, + public_key: KeyId, attributes: StorageAttributes, - ) - -> ClientResult<'_, reply::Agree, Self> - { + ) -> ClientResult<'_, reply::Agree, Self> { let r = self.request(request::Agree { mechanism, private_key, @@ -289,9 +302,11 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn attest(&mut self, signing_mechanism: Mechanism, private_key: KeyId) - -> ClientResult<'_, reply::Attest, Self> - { + fn attest( + &mut self, + signing_mechanism: Mechanism, + private_key: KeyId, + ) -> ClientResult<'_, reply::Attest, Self> { let r = self.request(request::Attest { signing_mechanism, private_key, @@ -300,24 +315,33 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn decrypt<'c>(&'c mut self, mechanism: Mechanism, key: KeyId, - message: &[u8], associated_data: &[u8], - nonce: &[u8], tag: &[u8], - ) - -> ClientResult<'c, reply::Decrypt, Self> - { + fn decrypt<'c>( + &'c mut self, + mechanism: Mechanism, + key: KeyId, + message: &[u8], + associated_data: &[u8], + nonce: &[u8], + tag: &[u8], + ) -> ClientResult<'c, reply::Decrypt, Self> { let message = Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?; - let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; + let associated_data = + Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; let nonce = ShortData::from_slice(nonce).map_err(|_| ClientError::DataTooLarge)?; let tag = ShortData::from_slice(tag).map_err(|_| ClientError::DataTooLarge)?; - let r = self.request(request::Decrypt { mechanism, key, message, associated_data, nonce, tag })?; + let r = self.request(request::Decrypt { + mechanism, + key, + message, + associated_data, + nonce, + tag, + })?; r.client.syscall(); Ok(r) } - fn delete(&mut self, key: KeyId) - -> ClientResult<'_, reply::Delete, Self> - { + fn delete(&mut self, key: KeyId) -> ClientResult<'_, reply::Delete, Self> { let r = self.request(request::Delete { key, // mechanism, @@ -327,17 +351,19 @@ pub trait CryptoClient: PollClient { } /// Skips deleting read-only / manufacture keys (currently, "low ID"). - fn delete_all(&mut self, location: Location) - -> ClientResult<'_, reply::DeleteAllKeys, Self> - { + fn delete_all(&mut self, location: Location) -> ClientResult<'_, reply::DeleteAllKeys, Self> { let r = self.request(request::DeleteAllKeys { location })?; r.client.syscall(); Ok(r) } - fn derive_key(&mut self, mechanism: Mechanism, base_key: KeyId, additional_data: Option, attributes: StorageAttributes) - -> ClientResult<'_, reply::DeriveKey, Self> - { + fn derive_key( + &mut self, + mechanism: Mechanism, + base_key: KeyId, + additional_data: Option, + attributes: StorageAttributes, + ) -> ClientResult<'_, reply::DeriveKey, Self> { let r = self.request(request::DeriveKey { mechanism, base_key, @@ -348,43 +374,62 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn deserialize_key<'c>(&'c mut self, mechanism: Mechanism, serialized_key: &[u8], - format: KeySerialization, attributes: StorageAttributes) - -> ClientResult<'c, reply::DeserializeKey, Self> - { - let serialized_key = Message::from_slice(serialized_key).map_err(|_| ClientError::DataTooLarge)?; + fn deserialize_key<'c>( + &'c mut self, + mechanism: Mechanism, + serialized_key: &[u8], + format: KeySerialization, + attributes: StorageAttributes, + ) -> ClientResult<'c, reply::DeserializeKey, Self> { + let serialized_key = + Message::from_slice(serialized_key).map_err(|_| ClientError::DataTooLarge)?; let r = self.request(request::DeserializeKey { - mechanism, serialized_key, format, attributes - } )?; + mechanism, + serialized_key, + format, + attributes, + })?; r.client.syscall(); Ok(r) } - fn encrypt<'c>(&'c mut self, mechanism: Mechanism, key: KeyId, - message: &[u8], associated_data: &[u8], nonce: Option) - -> ClientResult<'c, reply::Encrypt, Self> - { + fn encrypt<'c>( + &'c mut self, + mechanism: Mechanism, + key: KeyId, + message: &[u8], + associated_data: &[u8], + nonce: Option, + ) -> ClientResult<'c, reply::Encrypt, Self> { let message = Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?; - let associated_data = ShortData::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; - let r = self.request(request::Encrypt { mechanism, key, message, associated_data, nonce })?; + let associated_data = + ShortData::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; + let r = self.request(request::Encrypt { + mechanism, + key, + message, + associated_data, + nonce, + })?; r.client.syscall(); Ok(r) } - fn exists(&mut self, mechanism: Mechanism, key: KeyId) - -> ClientResult<'_, reply::Exists, Self> - { - let r = self.request(request::Exists { - key, - mechanism, - })?; + fn exists( + &mut self, + mechanism: Mechanism, + key: KeyId, + ) -> ClientResult<'_, reply::Exists, Self> { + let r = self.request(request::Exists { key, mechanism })?; r.client.syscall(); Ok(r) } - fn generate_key(&mut self, mechanism: Mechanism, attributes: StorageAttributes) - -> ClientResult<'_, reply::GenerateKey, Self> - { + fn generate_key( + &mut self, + mechanism: Mechanism, + attributes: StorageAttributes, + ) -> ClientResult<'_, reply::GenerateKey, Self> { let r = self.request(request::GenerateKey { mechanism, attributes, @@ -393,9 +438,11 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn generate_secret_key(&mut self, size: usize, persistence: Location) - -> ClientResult<'_, reply::GenerateSecretKey, Self> - { + fn generate_secret_key( + &mut self, + size: usize, + persistence: Location, + ) -> ClientResult<'_, reply::GenerateSecretKey, Self> { let r = self.request(request::GenerateSecretKey { size, attributes: StorageAttributes::new().set_persistence(persistence), @@ -404,25 +451,28 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn hash(&mut self, mechanism: Mechanism, message: Message) - -> ClientResult<'_, reply::Hash, Self> - { - let r = self.request(request::Hash { mechanism, message } )?; + fn hash( + &mut self, + mechanism: Mechanism, + message: Message, + ) -> ClientResult<'_, reply::Hash, Self> { + let r = self.request(request::Hash { mechanism, message })?; r.client.syscall(); Ok(r) } - fn random_bytes(&mut self, count: usize) - -> ClientResult<'_, reply::RandomBytes, Self> - { - let r = self.request(request::RandomBytes { count } )?; + fn random_bytes(&mut self, count: usize) -> ClientResult<'_, reply::RandomBytes, Self> { + let r = self.request(request::RandomBytes { count })?; r.client.syscall(); Ok(r) } - fn serialize_key(&mut self, mechanism: Mechanism, key: KeyId, format: KeySerialization) - -> ClientResult<'_, reply::SerializeKey, Self> - { + fn serialize_key( + &mut self, + mechanism: Mechanism, + key: KeyId, + format: KeySerialization, + ) -> ClientResult<'_, reply::SerializeKey, Self> { let r = self.request(request::SerializeKey { key, mechanism, @@ -438,9 +488,7 @@ pub trait CryptoClient: PollClient { key: KeyId, data: &[u8], format: SignatureSerialization, - ) - -> ClientResult<'c, reply::Sign, Self> - { + ) -> ClientResult<'c, reply::Sign, Self> { let r = self.request(request::Sign { key, mechanism, @@ -458,9 +506,7 @@ pub trait CryptoClient: PollClient { message: &[u8], signature: &[u8], format: SignatureSerialization, - ) - -> ClientResult<'c, reply::Verify, Self> - { + ) -> ClientResult<'c, reply::Verify, Self> { let r = self.request(request::Verify { mechanism, key, @@ -479,9 +525,12 @@ pub trait CryptoClient: PollClient { /// /// The implementations have been removed, so replace your usage with the /// methoed `unsafe_inject_shared_key`. - fn unsafe_inject_key(&mut self, mechanism: Mechanism, raw_key: &[u8], persistence: Location) - -> ClientResult<'_, reply::UnsafeInjectKey, Self> - { + fn unsafe_inject_key( + &mut self, + mechanism: Mechanism, + raw_key: &[u8], + persistence: Location, + ) -> ClientResult<'_, reply::UnsafeInjectKey, Self> { let r = self.request(request::UnsafeInjectKey { mechanism, raw_key: ShortData::from_slice(raw_key).unwrap(), @@ -491,9 +540,11 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn unsafe_inject_shared_key(&mut self, raw_key: &[u8], location: Location) - -> ClientResult<'_, reply::UnsafeInjectSharedKey, Self> - { + fn unsafe_inject_shared_key( + &mut self, + raw_key: &[u8], + location: Location, + ) -> ClientResult<'_, reply::UnsafeInjectSharedKey, Self> { let r = self.request(request::UnsafeInjectSharedKey { raw_key: ShortData::from_slice(raw_key).unwrap(), location, @@ -502,61 +553,71 @@ pub trait CryptoClient: PollClient { Ok(r) } - fn unwrap_key<'c>(&'c mut self, mechanism: Mechanism, wrapping_key: KeyId, wrapped_key: Message, - associated_data: &[u8], attributes: StorageAttributes) - -> ClientResult<'c, reply::UnwrapKey, Self> - { - let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; + fn unwrap_key<'c>( + &'c mut self, + mechanism: Mechanism, + wrapping_key: KeyId, + wrapped_key: Message, + associated_data: &[u8], + attributes: StorageAttributes, + ) -> ClientResult<'c, reply::UnwrapKey, Self> { + let associated_data = + Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; let r = self.request(request::UnwrapKey { mechanism, wrapping_key, wrapped_key, associated_data, - attributes + attributes, })?; r.client.syscall(); Ok(r) } - fn wrap_key(&mut self, mechanism: Mechanism, wrapping_key: KeyId, key: KeyId, - associated_data: &[u8]) - -> ClientResult<'_, reply::WrapKey, Self> - { - let associated_data = Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; - let r = self.request(request::WrapKey { mechanism, wrapping_key, key, associated_data })?; + fn wrap_key( + &mut self, + mechanism: Mechanism, + wrapping_key: KeyId, + key: KeyId, + associated_data: &[u8], + ) -> ClientResult<'_, reply::WrapKey, Self> { + let associated_data = + Message::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?; + let r = self.request(request::WrapKey { + mechanism, + wrapping_key, + key, + associated_data, + })?; r.client.syscall(); Ok(r) } - } /// Create counters, increment existing counters. pub trait CounterClient: PollClient { - - fn create_counter(&mut self, location: Location) - -> ClientResult<'_, reply::CreateCounter, Self> - { + fn create_counter( + &mut self, + location: Location, + ) -> ClientResult<'_, reply::CreateCounter, Self> { let r = self.request(request::CreateCounter { location })?; r.client.syscall(); Ok(r) } - fn increment_counter(&mut self, id: CounterId) - -> ClientResult<'_, reply::IncrementCounter, Self> - { + fn increment_counter( + &mut self, + id: CounterId, + ) -> ClientResult<'_, reply::IncrementCounter, Self> { let r = self.request(request::IncrementCounter { id })?; r.client.syscall(); Ok(r) } - } /// Read/Write/Delete files, iterate over directories. pub trait FilesystemClient: PollClient { - - fn debug_dump_store(&mut self) - -> ClientResult<'_, reply::DebugDumpStore, Self> - { + fn debug_dump_store(&mut self) -> ClientResult<'_, reply::DebugDumpStore, Self> { let r = self.request(request::DebugDumpStore {})?; r.client.syscall(); Ok(r) @@ -567,20 +628,18 @@ pub trait FilesystemClient: PollClient { location: Location, dir: PathBuf, not_before_filename: Option, - ) - -> ClientResult<'_, reply::ReadDirFirst, Self> - { - let r = self.request(request::ReadDirFirst { location, dir, not_before_filename } )?; + ) -> ClientResult<'_, reply::ReadDirFirst, Self> { + let r = self.request(request::ReadDirFirst { + location, + dir, + not_before_filename, + })?; r.client.syscall(); Ok(r) } - fn read_dir_next( - &mut self, - ) - -> ClientResult<'_, reply::ReadDirNext, Self> - { - let r = self.request(request::ReadDirNext {} )?; + fn read_dir_next(&mut self) -> ClientResult<'_, reply::ReadDirNext, Self> { + let r = self.request(request::ReadDirNext {})?; r.client.syscall(); Ok(r) } @@ -590,50 +649,58 @@ pub trait FilesystemClient: PollClient { location: Location, dir: PathBuf, user_attribute: Option, - ) - -> ClientResult<'_, reply::ReadDirFilesFirst, Self> - { - let r = self.request(request::ReadDirFilesFirst { dir, location, user_attribute } )?; + ) -> ClientResult<'_, reply::ReadDirFilesFirst, Self> { + let r = self.request(request::ReadDirFilesFirst { + dir, + location, + user_attribute, + })?; r.client.syscall(); Ok(r) } - fn read_dir_files_next(&mut self) - -> ClientResult<'_, reply::ReadDirFilesNext, Self> - { - let r = self.request(request::ReadDirFilesNext {} )?; + fn read_dir_files_next(&mut self) -> ClientResult<'_, reply::ReadDirFilesNext, Self> { + let r = self.request(request::ReadDirFilesNext {})?; r.client.syscall(); Ok(r) } - fn remove_dir(&mut self, location: Location, path: PathBuf) - -> ClientResult<'_, reply::RemoveDirAll, Self> - { - let r = self.request(request::RemoveDir { location, path } )?; + fn remove_dir( + &mut self, + location: Location, + path: PathBuf, + ) -> ClientResult<'_, reply::RemoveDirAll, Self> { + let r = self.request(request::RemoveDir { location, path })?; r.client.syscall(); Ok(r) } - fn remove_dir_all(&mut self, location: Location, path: PathBuf) - -> ClientResult<'_, reply::RemoveDirAll, Self> - { - let r = self.request(request::RemoveDirAll { location, path } )?; + fn remove_dir_all( + &mut self, + location: Location, + path: PathBuf, + ) -> ClientResult<'_, reply::RemoveDirAll, Self> { + let r = self.request(request::RemoveDirAll { location, path })?; r.client.syscall(); Ok(r) } - fn remove_file(&mut self, location: Location, path: PathBuf) - -> ClientResult<'_, reply::RemoveFile, Self> - { - let r = self.request(request::RemoveFile { location, path } )?; + fn remove_file( + &mut self, + location: Location, + path: PathBuf, + ) -> ClientResult<'_, reply::RemoveFile, Self> { + let r = self.request(request::RemoveFile { location, path })?; r.client.syscall(); Ok(r) } - fn read_file(&mut self, location: Location, path: PathBuf) - -> ClientResult<'_, reply::ReadFile, Self> - { - let r = self.request(request::ReadFile { location, path } )?; + fn read_file( + &mut self, + location: Location, + path: PathBuf, + ) -> ClientResult<'_, reply::ReadFile, Self> { + let r = self.request(request::ReadFile { location, path })?; r.client.syscall(); Ok(r) } @@ -641,18 +708,27 @@ pub trait FilesystemClient: PollClient { /// Fetch the Metadata for a file or directory /// /// If the file doesn't exists, return None - fn entry_metadata(&mut self, location: Location, path: PathBuf) - -> ClientResult<'_, reply::Metadata, Self> - { - let r = self.request(request::Metadata { location, path } )?; + fn entry_metadata( + &mut self, + location: Location, + path: PathBuf, + ) -> ClientResult<'_, reply::Metadata, Self> { + let r = self.request(request::Metadata { location, path })?; r.client.syscall(); Ok(r) } - fn locate_file(&mut self, location: Location, dir: Option, filename: PathBuf) - -> ClientResult<'_, reply::LocateFile, Self> - { - let r = self.request(request::LocateFile { location, dir, filename } )?; + fn locate_file( + &mut self, + location: Location, + dir: Option, + filename: PathBuf, + ) -> ClientResult<'_, reply::LocateFile, Self> { + let r = self.request(request::LocateFile { + location, + dir, + filename, + })?; r.client.syscall(); Ok(r) } @@ -663,65 +739,54 @@ pub trait FilesystemClient: PollClient { path: PathBuf, data: Message, user_attribute: Option, - ) - -> ClientResult<'_, reply::WriteFile, Self> - { + ) -> ClientResult<'_, reply::WriteFile, Self> { let r = self.request(request::WriteFile { - location, path, data, + location, + path, + data, user_attribute, - } )?; + })?; r.client.syscall(); Ok(r) } - } - /// All the other methods that are fit to expose. pub trait ManagementClient: PollClient { - - fn reboot(&mut self, to: reboot::To) - -> ClientResult<'_, reply::Reboot, Self> - { + fn reboot(&mut self, to: reboot::To) -> ClientResult<'_, reply::Reboot, Self> { let r = self.request(request::Reboot { to })?; r.client.syscall(); Ok(r) } - fn uptime(&mut self) - -> ClientResult<'_, reply::Uptime, Self> - { + fn uptime(&mut self) -> ClientResult<'_, reply::Uptime, Self> { let r = self.request(request::Uptime {})?; r.client.syscall(); Ok(r) } - - } - /// User-interfacing functionality. pub trait UiClient: PollClient { - - fn confirm_user_present(&mut self, timeout_milliseconds: u32) - -> ClientResult<'_, reply::RequestUserConsent, Self> - { + fn confirm_user_present( + &mut self, + timeout_milliseconds: u32, + ) -> ClientResult<'_, reply::RequestUserConsent, Self> { let r = self.request(request::RequestUserConsent { level: consent::Level::Normal, timeout_milliseconds, - } )?; + })?; r.client.syscall(); Ok(r) } fn wink(&mut self, duration: core::time::Duration) -> ClientResult<'_, reply::Wink, Self> { - let r = self.request(request::Wink { duration } )?; + let r = self.request(request::Wink { duration })?; r.client.syscall(); Ok(r) } } - // would be interesting to use proper futures, and something like // https://github.com/dflemstr/direct-executor/blob/master/src/lib.rs#L62-L66 @@ -733,11 +798,13 @@ macro_rules! block { let mut future_result = $future_result; loop { match future_result.poll() { - core::task::Poll::Ready(result) => { break result; }, - core::task::Poll::Pending => {}, + core::task::Poll::Ready(result) => { + break result; + } + core::task::Poll::Pending => {} } } - }} + }}; } #[macro_export] @@ -747,11 +814,13 @@ macro_rules! syscall { let mut future_result = $pre_future_result.expect("no client error"); loop { match future_result.poll() { - core::task::Poll::Ready(result) => { break result.expect("no errors"); }, - core::task::Poll::Pending => {}, + core::task::Poll::Ready(result) => { + break result.expect("no errors"); + } + core::task::Poll::Pending => {} } } - }} + }}; } #[macro_export] @@ -761,10 +830,11 @@ macro_rules! try_syscall { let mut future_result = $pre_future_result.expect("no client error"); loop { match future_result.poll() { - core::task::Poll::Ready(result) => { break result; }, - core::task::Poll::Pending => {}, + core::task::Poll::Ready(result) => { + break result; + } + core::task::Poll::Pending => {} } } - }} + }}; } - diff --git a/src/client/mechanisms.rs b/src/client/mechanisms.rs index 630391286a1..020b11cfe6c 100644 --- a/src/client/mechanisms.rs +++ b/src/client/mechanisms.rs @@ -4,17 +4,19 @@ use super::*; impl Aes256Cbc for ClientImplementation {} pub trait Aes256Cbc: CryptoClient { - fn decrypt_aes256cbc<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Decrypt, Self> - { - self.decrypt( - Mechanism::Aes256Cbc, key, message, &[], &[], &[], - ) - } - - fn wrap_key_aes256cbc(&mut self, wrapping_key: KeyId, key: KeyId) - -> ClientResult<'_, reply::WrapKey, Self> - { + fn decrypt_aes256cbc<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Decrypt, Self> { + self.decrypt(Mechanism::Aes256Cbc, key, message, &[], &[], &[]) + } + + fn wrap_key_aes256cbc( + &mut self, + wrapping_key: KeyId, + key: KeyId, + ) -> ClientResult<'_, reply::WrapKey, Self> { self.wrap_key(Mechanism::Aes256Cbc, wrapping_key, key, &[]) } } @@ -23,42 +25,78 @@ pub trait Aes256Cbc: CryptoClient { impl Chacha8Poly1305 for ClientImplementation {} pub trait Chacha8Poly1305: CryptoClient { - fn decrypt_chacha8poly1305<'c>(&'c mut self, key: KeyId, message: &[u8], associated_data: &[u8], - nonce: &[u8], tag: &[u8]) - -> ClientResult<'c, reply::Decrypt, Self> - { - self.decrypt(Mechanism::Chacha8Poly1305, key, message, associated_data, nonce, tag) + fn decrypt_chacha8poly1305<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + associated_data: &[u8], + nonce: &[u8], + tag: &[u8], + ) -> ClientResult<'c, reply::Decrypt, Self> { + self.decrypt( + Mechanism::Chacha8Poly1305, + key, + message, + associated_data, + nonce, + tag, + ) } - fn encrypt_chacha8poly1305<'c>(&'c mut self, key: KeyId, message: &[u8], associated_data: &[u8], - nonce: Option<&[u8; 12]>) - -> ClientResult<'c, reply::Encrypt, Self> - { - self.encrypt(Mechanism::Chacha8Poly1305, key, message, associated_data, - nonce.and_then(|nonce| ShortData::from_slice(nonce).ok())) + fn encrypt_chacha8poly1305<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + associated_data: &[u8], + nonce: Option<&[u8; 12]>, + ) -> ClientResult<'c, reply::Encrypt, Self> { + self.encrypt( + Mechanism::Chacha8Poly1305, + key, + message, + associated_data, + nonce.and_then(|nonce| ShortData::from_slice(nonce).ok()), + ) } - fn generate_chacha8poly1305_key(&mut self, persistence: Location) - -> ClientResult<'_, reply::GenerateKey, Self> - { - self.generate_key(Mechanism::Chacha8Poly1305, StorageAttributes::new().set_persistence(persistence)) + fn generate_chacha8poly1305_key( + &mut self, + persistence: Location, + ) -> ClientResult<'_, reply::GenerateKey, Self> { + self.generate_key( + Mechanism::Chacha8Poly1305, + StorageAttributes::new().set_persistence(persistence), + ) } - fn unwrap_key_chacha8poly1305<'c>(&'c mut self, wrapping_key: KeyId, wrapped_key: &[u8], - associated_data: &[u8], location: Location) - -> ClientResult<'c, reply::UnwrapKey, Self> - { - self.unwrap_key(Mechanism::Chacha8Poly1305, wrapping_key, - Message::from_slice(wrapped_key).map_err(|_| ClientError::DataTooLarge)?, - associated_data, - StorageAttributes::new().set_persistence(location)) + fn unwrap_key_chacha8poly1305<'c>( + &'c mut self, + wrapping_key: KeyId, + wrapped_key: &[u8], + associated_data: &[u8], + location: Location, + ) -> ClientResult<'c, reply::UnwrapKey, Self> { + self.unwrap_key( + Mechanism::Chacha8Poly1305, + wrapping_key, + Message::from_slice(wrapped_key).map_err(|_| ClientError::DataTooLarge)?, + associated_data, + StorageAttributes::new().set_persistence(location), + ) } - fn wrap_key_chacha8poly1305<'c>(&'c mut self, wrapping_key: KeyId, key: KeyId, - associated_data: &[u8]) - -> ClientResult<'c, reply::WrapKey, Self> - { - self.wrap_key(Mechanism::Chacha8Poly1305, wrapping_key, key, associated_data) + fn wrap_key_chacha8poly1305<'c>( + &'c mut self, + wrapping_key: KeyId, + key: KeyId, + associated_data: &[u8], + ) -> ClientResult<'c, reply::WrapKey, Self> { + self.wrap_key( + Mechanism::Chacha8Poly1305, + wrapping_key, + key, + associated_data, + ) } } @@ -66,124 +104,195 @@ pub trait Chacha8Poly1305: CryptoClient { impl HmacBlake2s for ClientImplementation {} pub trait HmacBlake2s: CryptoClient { - fn hmacblake2s_derive_key(&mut self, base_key: KeyId, message: &[u8], persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { + fn hmacblake2s_derive_key( + &mut self, + base_key: KeyId, + message: &[u8], + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { self.derive_key( - Mechanism::HmacBlake2s, base_key, + Mechanism::HmacBlake2s, + base_key, Some(MediumData::from_slice(message).map_err(|_| ClientError::DataTooLarge)?), - StorageAttributes::new().set_persistence(persistence)) + StorageAttributes::new().set_persistence(persistence), + ) } - fn sign_hmacblake2s<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Sign, Self> - { - self.sign(Mechanism::HmacBlake2s, key, message, SignatureSerialization::Raw) + fn sign_hmacblake2s<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Sign, Self> { + self.sign( + Mechanism::HmacBlake2s, + key, + message, + SignatureSerialization::Raw, + ) } - } #[cfg(feature = "hmac-sha1")] impl HmacSha1 for ClientImplementation {} pub trait HmacSha1: CryptoClient { - fn hmacsha1_derive_key(&mut self, base_key: KeyId, message: &[u8], persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { + fn hmacsha1_derive_key( + &mut self, + base_key: KeyId, + message: &[u8], + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { self.derive_key( - Mechanism::HmacSha1, base_key, + Mechanism::HmacSha1, + base_key, Some(MediumData::from_slice(message).map_err(|_| ClientError::DataTooLarge)?), - StorageAttributes::new().set_persistence(persistence)) + StorageAttributes::new().set_persistence(persistence), + ) } - fn sign_hmacsha1<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Sign, Self> - { - self.sign(Mechanism::HmacSha1, key, message, SignatureSerialization::Raw) + fn sign_hmacsha1<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Sign, Self> { + self.sign( + Mechanism::HmacSha1, + key, + message, + SignatureSerialization::Raw, + ) } - } #[cfg(feature = "hmac-sha256")] impl HmacSha256 for ClientImplementation {} pub trait HmacSha256: CryptoClient { - fn hmacsha256_derive_key(&mut self, base_key: KeyId, message: &[u8], persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { + fn hmacsha256_derive_key( + &mut self, + base_key: KeyId, + message: &[u8], + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { self.derive_key( - Mechanism::HmacSha256, base_key, + Mechanism::HmacSha256, + base_key, Some(MediumData::from_slice(message).map_err(|_| ClientError::DataTooLarge)?), - StorageAttributes::new().set_persistence(persistence)) + StorageAttributes::new().set_persistence(persistence), + ) } - fn sign_hmacsha256<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Sign, Self> - { - self.sign(Mechanism::HmacSha256, key, message, SignatureSerialization::Raw) + fn sign_hmacsha256<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Sign, Self> { + self.sign( + Mechanism::HmacSha256, + key, + message, + SignatureSerialization::Raw, + ) } - } #[cfg(feature = "hmac-sha512")] impl HmacSha512 for ClientImplementation {} pub trait HmacSha512: CryptoClient { - fn hmacsha512_derive_key(&mut self, base_key: KeyId, message: &[u8], persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { + fn hmacsha512_derive_key( + &mut self, + base_key: KeyId, + message: &[u8], + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { self.derive_key( - Mechanism::HmacSha512, base_key, + Mechanism::HmacSha512, + base_key, Some(MediumData::from_slice(message).map_err(|_| ClientError::DataTooLarge)?), - StorageAttributes::new().set_persistence(persistence)) + StorageAttributes::new().set_persistence(persistence), + ) } - fn sign_hmacsha512<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Sign, Self> - { - self.sign(Mechanism::HmacSha512, key, message, SignatureSerialization::Raw) + fn sign_hmacsha512<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Sign, Self> { + self.sign( + Mechanism::HmacSha512, + key, + message, + SignatureSerialization::Raw, + ) } - } #[cfg(feature = "ed255")] impl Ed255 for ClientImplementation {} pub trait Ed255: CryptoClient { - fn generate_ed255_private_key(&mut self, persistence: Location) - -> ClientResult<'_, reply::GenerateKey, Self> - { - self.generate_key(Mechanism::Ed255, StorageAttributes::new().set_persistence(persistence)) + fn generate_ed255_private_key( + &mut self, + persistence: Location, + ) -> ClientResult<'_, reply::GenerateKey, Self> { + self.generate_key( + Mechanism::Ed255, + StorageAttributes::new().set_persistence(persistence), + ) } - fn derive_ed255_public_key(&mut self, private_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { - self.derive_key(Mechanism::Ed255, private_key, None, StorageAttributes::new().set_persistence(persistence)) + fn derive_ed255_public_key( + &mut self, + private_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { + self.derive_key( + Mechanism::Ed255, + private_key, + None, + StorageAttributes::new().set_persistence(persistence), + ) } - fn deserialize_ed255_key<'c>(&'c mut self, serialized_key: &[u8], format: KeySerialization, attributes: StorageAttributes) - -> ClientResult<'c, reply::DeserializeKey, Self> - { + fn deserialize_ed255_key<'c>( + &'c mut self, + serialized_key: &[u8], + format: KeySerialization, + attributes: StorageAttributes, + ) -> ClientResult<'c, reply::DeserializeKey, Self> { self.deserialize_key(Mechanism::Ed255, serialized_key, format, attributes) } - fn serialize_ed255_key(&mut self, key: KeyId, format: KeySerialization) - -> ClientResult<'_, reply::SerializeKey, Self> - { + fn serialize_ed255_key( + &mut self, + key: KeyId, + format: KeySerialization, + ) -> ClientResult<'_, reply::SerializeKey, Self> { self.serialize_key(Mechanism::Ed255, key, format) } - fn sign_ed255<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Sign, Self> - { + fn sign_ed255<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Sign, Self> { self.sign(Mechanism::Ed255, key, message, SignatureSerialization::Raw) } - fn verify_ed255<'c>(&'c mut self, key: KeyId, message: &[u8], signature: &[u8]) - -> ClientResult<'c, reply::Verify, Self> - { - self.verify(Mechanism::Ed255, key, message, signature, SignatureSerialization::Raw) + fn verify_ed255<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + signature: &[u8], + ) -> ClientResult<'c, reply::Verify, Self> { + self.verify( + Mechanism::Ed255, + key, + message, + signature, + SignatureSerialization::Raw, + ) } } @@ -191,27 +300,43 @@ pub trait Ed255: CryptoClient { impl P256 for ClientImplementation {} pub trait P256: CryptoClient { - fn generate_p256_private_key(&mut self, persistence: Location) - -> ClientResult<'_, reply::GenerateKey, Self> - { - self.generate_key(Mechanism::P256, StorageAttributes::new().set_persistence(persistence)) + fn generate_p256_private_key( + &mut self, + persistence: Location, + ) -> ClientResult<'_, reply::GenerateKey, Self> { + self.generate_key( + Mechanism::P256, + StorageAttributes::new().set_persistence(persistence), + ) } - fn derive_p256_public_key(&mut self, private_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { - self.derive_key(Mechanism::P256, private_key, None, StorageAttributes::new().set_persistence(persistence)) + fn derive_p256_public_key( + &mut self, + private_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { + self.derive_key( + Mechanism::P256, + private_key, + None, + StorageAttributes::new().set_persistence(persistence), + ) } - fn deserialize_p256_key<'c>(&'c mut self, serialized_key: &[u8], format: KeySerialization, attributes: StorageAttributes) - -> ClientResult<'c, reply::DeserializeKey, Self> - { + fn deserialize_p256_key<'c>( + &'c mut self, + serialized_key: &[u8], + format: KeySerialization, + attributes: StorageAttributes, + ) -> ClientResult<'c, reply::DeserializeKey, Self> { self.deserialize_key(Mechanism::P256, serialized_key, format, attributes) } - fn serialize_p256_key(&mut self, key: KeyId, format: KeySerialization) - -> ClientResult<'_, reply::SerializeKey, Self> - { + fn serialize_p256_key( + &mut self, + key: KeyId, + format: KeySerialization, + ) -> ClientResult<'_, reply::SerializeKey, Self> { self.serialize_key(Mechanism::P256, key, format) } @@ -221,21 +346,36 @@ pub trait P256: CryptoClient { // // on the other hand: if users need sha256, then if the service runs in secure trustzone // domain, we'll maybe need two copies of the sha2 code - fn sign_p256<'c>(&'c mut self, key: KeyId, message: &[u8], format: SignatureSerialization) - -> ClientResult<'c, reply::Sign, Self> - { + fn sign_p256<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + format: SignatureSerialization, + ) -> ClientResult<'c, reply::Sign, Self> { self.sign(Mechanism::P256, key, message, format) } - fn verify_p256<'c>(&'c mut self, key: KeyId, message: &[u8], signature: &[u8]) - -> ClientResult<'c, reply::Verify, Self> - { - self.verify(Mechanism::P256, key, message, signature, SignatureSerialization::Raw) + fn verify_p256<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + signature: &[u8], + ) -> ClientResult<'c, reply::Verify, Self> { + self.verify( + Mechanism::P256, + key, + message, + signature, + SignatureSerialization::Raw, + ) } - fn agree_p256(&mut self, private_key: KeyId, public_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::Agree, Self> - { + fn agree_p256( + &mut self, + private_key: KeyId, + public_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::Agree, Self> { self.agree( Mechanism::P256, private_key, @@ -249,16 +389,24 @@ pub trait P256: CryptoClient { impl Sha256 for ClientImplementation {} pub trait Sha256: CryptoClient { - fn sha256_derive_key(&mut self, shared_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { - self.derive_key(Mechanism::Sha256, shared_key, None, StorageAttributes::new().set_persistence(persistence)) + fn sha256_derive_key( + &mut self, + shared_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { + self.derive_key( + Mechanism::Sha256, + shared_key, + None, + StorageAttributes::new().set_persistence(persistence), + ) } - fn hash_sha256<'c>(&'c mut self, message: &[u8]) - -> ClientResult<'c, reply::Hash, Self> - { - self.hash(Mechanism::Sha256, Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?) + fn hash_sha256<'c>(&'c mut self, message: &[u8]) -> ClientResult<'c, reply::Hash, Self> { + self.hash( + Mechanism::Sha256, + Message::from_slice(message).map_err(|_| ClientError::DataTooLarge)?, + ) } } @@ -266,15 +414,19 @@ pub trait Sha256: CryptoClient { impl Tdes for ClientImplementation {} pub trait Tdes: CryptoClient { - fn decrypt_tdes<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Decrypt, Self> - { + fn decrypt_tdes<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Decrypt, Self> { self.decrypt(Mechanism::Tdes, key, message, &[], &[], &[]) } - fn encrypt_tdes<'c>(&'c mut self, key: KeyId, message: &[u8]) - -> ClientResult<'c, reply::Encrypt, Self> - { + fn encrypt_tdes<'c>( + &'c mut self, + key: KeyId, + message: &[u8], + ) -> ClientResult<'c, reply::Encrypt, Self> { self.encrypt(Mechanism::Tdes, key, message, &[], None) } } @@ -283,10 +435,10 @@ pub trait Tdes: CryptoClient { impl Totp for ClientImplementation {} pub trait Totp: CryptoClient { - fn sign_totp(&mut self, key: KeyId, timestamp: u64) - -> ClientResult<'_, reply::Sign, Self> - { - self.sign(Mechanism::Totp, key, + fn sign_totp(&mut self, key: KeyId, timestamp: u64) -> ClientResult<'_, reply::Sign, Self> { + self.sign( + Mechanism::Totp, + key, timestamp.to_le_bytes().as_ref(), SignatureSerialization::Raw, ) @@ -297,21 +449,35 @@ pub trait Totp: CryptoClient { impl X255 for ClientImplementation {} pub trait X255: CryptoClient { - fn generate_x255_secret_key(&mut self, persistence: Location) - -> ClientResult<'_, reply::GenerateKey, Self> - { - self.generate_key(Mechanism::X255, StorageAttributes::new().set_persistence(persistence)) + fn generate_x255_secret_key( + &mut self, + persistence: Location, + ) -> ClientResult<'_, reply::GenerateKey, Self> { + self.generate_key( + Mechanism::X255, + StorageAttributes::new().set_persistence(persistence), + ) } - fn derive_x255_public_key(&mut self, secret_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::DeriveKey, Self> - { - self.derive_key(Mechanism::X255, secret_key, None, StorageAttributes::new().set_persistence(persistence)) + fn derive_x255_public_key( + &mut self, + secret_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::DeriveKey, Self> { + self.derive_key( + Mechanism::X255, + secret_key, + None, + StorageAttributes::new().set_persistence(persistence), + ) } - fn agree_x255(&mut self, private_key: KeyId, public_key: KeyId, persistence: Location) - -> ClientResult<'_, reply::Agree, Self> - { + fn agree_x255( + &mut self, + private_key: KeyId, + public_key: KeyId, + persistence: Location, + ) -> ClientResult<'_, reply::Agree, Self> { self.agree( Mechanism::X255, private_key, @@ -320,4 +486,3 @@ pub trait X255: CryptoClient { ) } } - diff --git a/src/config.rs b/src/config.rs index 29e452aa654..4e92fd23093 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,35 +17,34 @@ pub const MAX_KEY_MATERIAL_LENGTH: usize = 128; // must be above + 4 pub const MAX_SERIALIZED_KEY_LENGTH: usize = 132; cfg_if::cfg_if! { - if #[cfg(feature = "clients-12")] { - pub type MAX_SERVICE_CLIENTS = consts::U12; - } else if #[cfg(feature = "clients-11")] { - pub type MAX_SERVICE_CLIENTS = consts::U11; - } else if #[cfg(feature = "clients-10")] { - pub type MAX_SERVICE_CLIENTS = consts::U10; - } else if #[cfg(feature = "clients-9")] { - pub type MAX_SERVICE_CLIENTS = consts::U9; - } else if #[cfg(feature = "clients-8")] { - pub type MAX_SERVICE_CLIENTS = consts::U8; - } else if #[cfg(feature = "clients-7")] { - pub type MAX_SERVICE_CLIENTS = consts::U7; - } else if #[cfg(feature = "clients-6")] { - pub type MAX_SERVICE_CLIENTS = consts::U6; - } else if #[cfg(feature = "clients-5")] { - pub type MAX_SERVICE_CLIENTS = consts::U5; - } else if #[cfg(feature = "clients-4")] { - pub type MAX_SERVICE_CLIENTS = consts::U4; - } else if #[cfg(feature = "clients-3")] { - pub type MAX_SERVICE_CLIENTS = consts::U3; - } else if #[cfg(feature = "clients-2")] { - pub type MAX_SERVICE_CLIENTS = consts::U2; - } else if #[cfg(feature = "clients-1")] { - pub type MAX_SERVICE_CLIENTS = consts::U1; - } + if #[cfg(feature = "clients-12")] { + pub type MAX_SERVICE_CLIENTS = consts::U12; + } else if #[cfg(feature = "clients-11")] { + pub type MAX_SERVICE_CLIENTS = consts::U11; + } else if #[cfg(feature = "clients-10")] { + pub type MAX_SERVICE_CLIENTS = consts::U10; + } else if #[cfg(feature = "clients-9")] { + pub type MAX_SERVICE_CLIENTS = consts::U9; + } else if #[cfg(feature = "clients-8")] { + pub type MAX_SERVICE_CLIENTS = consts::U8; + } else if #[cfg(feature = "clients-7")] { + pub type MAX_SERVICE_CLIENTS = consts::U7; + } else if #[cfg(feature = "clients-6")] { + pub type MAX_SERVICE_CLIENTS = consts::U6; + } else if #[cfg(feature = "clients-5")] { + pub type MAX_SERVICE_CLIENTS = consts::U5; + } else if #[cfg(feature = "clients-4")] { + pub type MAX_SERVICE_CLIENTS = consts::U4; + } else if #[cfg(feature = "clients-3")] { + pub type MAX_SERVICE_CLIENTS = consts::U3; + } else if #[cfg(feature = "clients-2")] { + pub type MAX_SERVICE_CLIENTS = consts::U2; + } else if #[cfg(feature = "clients-1")] { + pub type MAX_SERVICE_CLIENTS = consts::U1; + } } pub const MAX_SHORT_DATA_LENGTH: usize = 128; pub const MAX_SIGNATURE_LENGTH: usize = 72; pub const MAX_USER_ATTRIBUTE_LENGTH: usize = 256; pub const USER_ATTRIBUTE_NUMBER: u8 = 37; - diff --git a/src/error.rs b/src/error.rs index be12b1a9c88..861a92ba060 100644 --- a/src/error.rs +++ b/src/error.rs @@ -63,4 +63,3 @@ pub enum Error { // } // } // } - diff --git a/src/key.rs b/src/key.rs index ce74889773d..47e3df208d6 100644 --- a/src/key.rs +++ b/src/key.rs @@ -5,12 +5,12 @@ use zeroize::Zeroize; pub use crate::Bytes; use crate::{ - Error, config::{MAX_KEY_MATERIAL_LENGTH, MAX_SERIALIZED_KEY_LENGTH}, + Error, }; -pub type Material = Vec; -pub type SerializedKeyBytes = Vec; +pub type Material = Vec; +pub type SerializedKeyBytes = Vec; // We don't implement serde to make sure nobody inadvertently still uses it // Should we use references here only? @@ -23,15 +23,15 @@ pub type SerializedKeyBytes = Vec; /// [dictum]: https://twitter.com/SchmiegSophie/status/1264567198091079681 #[derive(Clone, Debug, /*DeserializeIndexed,*/ Eq, PartialEq, /*SerializeIndexed,*/ Zeroize)] pub struct Key { - pub flags: Flags, - pub kind: Kind, - pub material: Material, + pub flags: Flags, + pub kind: Kind, + pub material: Material, } #[derive(Clone, Debug, /*DeserializeIndexed,*/ Eq, PartialEq, /*SerializeIndexed,*/ Zeroize)] pub struct Info { - pub flags: Flags, - pub kind: Kind, + pub flags: Flags, + pub kind: Kind, } impl Info { @@ -43,7 +43,10 @@ impl Info { impl From for Info { fn from(kind: Kind) -> Self { - Self { flags: Default::default(), kind } + Self { + flags: Default::default(), + kind, + } } } @@ -92,8 +95,12 @@ impl Key { let mut buffer = SerializedKeyBytes::new(); // big-endian here to ensure the first bit is enough to check compatibility // on breaking format change - buffer.extend_from_slice(&self.flags.bits().to_be_bytes()).unwrap(); - buffer.extend_from_slice(&(self.kind.code()).to_be_bytes()).unwrap(); + buffer + .extend_from_slice(&self.flags.bits().to_be_bytes()) + .unwrap(); + buffer + .extend_from_slice(&(self.kind.code()).to_be_bytes()) + .unwrap(); // can't fail, since MAX_SERIALIZED_KEY_LENGTH is defined as MAX_KEY_MATERIAL_LENGTH + 4 buffer.extend_from_slice(&self.material).unwrap(); buffer @@ -108,7 +115,8 @@ impl Key { let flags = Flags::from_bits(flags_bits).ok_or(Error::InvalidSerializedKey)?; let kind_bits = u16::from_be_bytes([info[2], info[3]]); - let kind = Kind::try_from(kind_bits, material.len()).map_err(|_| Error::InvalidSerializedKey)?; + let kind = + Kind::try_from(kind_bits, material.len()).map_err(|_| Error::InvalidSerializedKey)?; Ok(Key { flags, diff --git a/src/lib.rs b/src/lib.rs index f518658c1e7..613b851ab6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,13 +33,13 @@ pub mod types; pub mod virt; pub use api::Reply; -pub use error::Error; pub use client::{Client, ClientImplementation}; +pub use error::Error; /// The trait that platforms need to implement to use Trussed. pub use platform::Platform; pub use service::Service; -pub use cbor_smol::{cbor_serialize, cbor_serialize_bytes, cbor_deserialize}; +pub use cbor_smol::{cbor_deserialize, cbor_serialize, cbor_serialize_bytes}; pub use heapless_bytes::Bytes; pub use postcard::{from_bytes as postcard_deserialize, to_slice as postcard_serialize}; @@ -56,4 +56,3 @@ mod tests; #[cfg(test)] #[macro_use] extern crate serial_test; - diff --git a/src/mechanisms.rs b/src/mechanisms.rs index f55392a4260..65b5d37bce7 100644 --- a/src/mechanisms.rs +++ b/src/mechanisms.rs @@ -77,4 +77,3 @@ mod x255; // _ => MechanismEnum::NotImplemented, // } // } - diff --git a/src/mechanisms/aes256cbc.rs b/src/mechanisms/aes256cbc.rs index 81e3ee00b7c..2e5aca7728a 100644 --- a/src/mechanisms/aes256cbc.rs +++ b/src/mechanisms/aes256cbc.rs @@ -1,4 +1,3 @@ - use crate::api::*; // use crate::config::*; use crate::error::Error; @@ -6,16 +5,16 @@ use crate::service::*; use crate::types::*; #[cfg(feature = "aes256-cbc")] -impl Encrypt for super::Aes256Cbc -{ +impl Encrypt for super::Aes256Cbc { /// Encrypts the input *with zero IV* - fn encrypt(keystore: &mut impl Keystore, request: &request::Encrypt) - -> Result - { - use block_modes::{BlockMode, Cbc}; - // use block_modes::Cbc; - use block_modes::block_padding::ZeroPadding; - use aes::Aes256; + fn encrypt( + keystore: &mut impl Keystore, + request: &request::Encrypt, + ) -> Result { + use block_modes::{BlockMode, Cbc}; + // use block_modes::Cbc; + use aes::Aes256; + use block_modes::block_padding::ZeroPadding; // TODO: perhaps use NoPadding and have client pad, to emphasize spec-conformance? type Aes256Cbc = Cbc; @@ -27,45 +26,55 @@ impl Encrypt for super::Aes256Cbc let symmetric_key: [u8; 32] = keystore .load_key(key::Secrecy::Secret, None, &key_id)? - .material.as_slice().try_into() + .material + .as_slice() + .try_into() .map_err(|_| Error::InternalError)?; let zero_iv = [0u8; 16]; - let cipher = Aes256Cbc::new_from_slices(&symmetric_key, &zero_iv).unwrap(); + let cipher = Aes256Cbc::new_from_slices(&symmetric_key, &zero_iv).unwrap(); - // buffer must have enough space for message+padding - let mut buffer = request.message.clone(); - // // copy message to the buffer - // let pos = plaintext.len(); - // buffer[..pos].copy_from_slice(plaintext); + // buffer must have enough space for message+padding + let mut buffer = request.message.clone(); + // // copy message to the buffer + // let pos = plaintext.len(); + // buffer[..pos].copy_from_slice(plaintext); let l = buffer.len(); // hprintln!(" aes256cbc encrypting l = {}B: {:?}", l, &buffer).ok(); // Encrypt message in-place. // &buffer[..pos] is used as a message and &buffer[pos..] as a reserved space for padding. // The padding space should be big enough for padding, otherwise method will return Err(BlockModeError). - let ciphertext = cipher.encrypt(&mut buffer, l).unwrap(); + let ciphertext = cipher.encrypt(&mut buffer, l).unwrap(); let ciphertext = Message::from_slice(ciphertext).unwrap(); - Ok(reply::Encrypt { ciphertext, nonce: ShortData::new(), tag: ShortData::new() }) + Ok(reply::Encrypt { + ciphertext, + nonce: ShortData::new(), + tag: ShortData::new(), + }) } } #[cfg(feature = "aes256-cbc")] -impl WrapKey for super::Aes256Cbc -{ - fn wrap_key(keystore: &mut impl Keystore, request: &request::WrapKey) - -> Result - { +impl WrapKey for super::Aes256Cbc { + fn wrap_key( + keystore: &mut impl Keystore, + request: &request::WrapKey, + ) -> Result { // TODO: need to check both secret and private keys // let path = keystore.key_path(key::Secrecy::Secret, &request.key)?; // let (serialized_key, _location) = keystore.load_key_unchecked(&path)?; // let message: Message = serialized_key.material.try_to_byte_buf().map_err(|_| Error::InternalError)?; - let message = Message::from_slice(keystore - .load_key(key::Secrecy::Secret, None, &request.key)? - .material.as_slice()).map_err(|_| Error::InternalError)?; + let message = Message::from_slice( + keystore + .load_key(key::Secrecy::Secret, None, &request.key)? + .material + .as_slice(), + ) + .map_err(|_| Error::InternalError)?; let encryption_request = request::Encrypt { mechanism: Mechanism::Aes256Cbc, @@ -83,15 +92,15 @@ impl WrapKey for super::Aes256Cbc } #[cfg(feature = "aes256-cbc")] -impl Decrypt for super::Aes256Cbc -{ - fn decrypt(keystore: &mut impl Keystore, request: &request::Decrypt) - -> Result - { - use block_modes::{BlockMode, Cbc}; - // use block_modes::Cbc; - use block_modes::block_padding::ZeroPadding; - use aes::Aes256; +impl Decrypt for super::Aes256Cbc { + fn decrypt( + keystore: &mut impl Keystore, + request: &request::Decrypt, + ) -> Result { + use block_modes::{BlockMode, Cbc}; + // use block_modes::Cbc; + use aes::Aes256; + use block_modes::block_padding::ZeroPadding; // TODO: perhaps use NoPadding and have client pad, to emphasize spec-conformance? type Aes256Cbc = Cbc; @@ -99,18 +108,19 @@ impl Decrypt for super::Aes256Cbc let key_id = request.key; let symmetric_key: [u8; 32] = keystore .load_key(key::Secrecy::Secret, None, &key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; let zero_iv = [0u8; 16]; - let cipher = Aes256Cbc::new_from_slices(&symmetric_key, &zero_iv).unwrap(); + let cipher = Aes256Cbc::new_from_slices(&symmetric_key, &zero_iv).unwrap(); - // buffer must have enough space for message+padding - let mut buffer = request.message.clone(); - // // copy message to the buffer - // let pos = plaintext.len(); - // buffer[..pos].copy_from_slice(plaintext); + // buffer must have enough space for message+padding + let mut buffer = request.message.clone(); + // // copy message to the buffer + // let pos = plaintext.len(); + // buffer[..pos].copy_from_slice(plaintext); // let l = buffer.len(); // Decrypt message in-place. @@ -118,11 +128,13 @@ impl Decrypt for super::Aes256Cbc // if after decoding message has malformed padding. // hprintln!("encrypted: {:?}", &buffer).ok(); // hprintln!("symmetric key: {:?}", &symmetric_key).ok(); - let plaintext = cipher.decrypt(&mut buffer).unwrap(); + let plaintext = cipher.decrypt(&mut buffer).unwrap(); // hprintln!("decrypted: {:?}", &plaintext).ok(); let plaintext = Message::from_slice(plaintext).unwrap(); - Ok(reply::Decrypt { plaintext: Some(plaintext) }) + Ok(reply::Decrypt { + plaintext: Some(plaintext), + }) } } diff --git a/src/mechanisms/chacha8poly1305.rs b/src/mechanisms/chacha8poly1305.rs index c237c1158cf..10ee607559a 100644 --- a/src/mechanisms/chacha8poly1305.rs +++ b/src/mechanisms/chacha8poly1305.rs @@ -1,4 +1,3 @@ - use crate::api::*; // use crate::config::*; use crate::error::Error; @@ -11,11 +10,11 @@ use crate::types::*; #[cfg(feature = "chacha8-poly1305")] impl GenerateKey for super::Chacha8Poly1305 { - #[inline(never)] - fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey) - -> Result - { + fn generate_key( + keystore: &mut impl Keystore, + request: &request::GenerateKey, + ) -> Result { use rand_core::RngCore as _; // 32 bytes entropy @@ -53,17 +52,21 @@ fn increment_nonce(nonce: &mut [u8]) -> Result<(), Error> { } #[cfg(feature = "chacha8-poly1305")] -impl Decrypt for super::Chacha8Poly1305 -{ +impl Decrypt for super::Chacha8Poly1305 { #[inline(never)] - fn decrypt(keystore: &mut impl Keystore, request: &request::Decrypt) - -> Result - { - use chacha20poly1305::ChaCha8Poly1305; + fn decrypt( + keystore: &mut impl Keystore, + request: &request::Decrypt, + ) -> Result { use chacha20poly1305::aead::{AeadInPlace, NewAead}; + use chacha20poly1305::ChaCha8Poly1305; let serialized_material = keystore - .load_key(key::Secrecy::Secret, Some(key::Kind::Symmetric32Nonce(12)), &request.key)? + .load_key( + key::Secrecy::Secret, + Some(key::Kind::Symmetric32Nonce(12)), + &request.key, + )? .material; let serialized = serialized_material.as_slice(); @@ -80,39 +83,38 @@ impl Decrypt for super::Chacha8Poly1305 let nonce = GenericArray::from_slice(&request.nonce); let tag = GenericArray::from_slice(&request.tag); - let outcome = aead.decrypt_in_place_detached( - nonce, &request.associated_data, &mut plaintext, tag); + let outcome = + aead.decrypt_in_place_detached(nonce, &request.associated_data, &mut plaintext, tag); // outcome.map_err(|_| Error::AeadError)?; - Ok(reply::Decrypt { plaintext: { - if outcome.is_ok() { - Some(plaintext) - } else { - None - } - }}) + Ok(reply::Decrypt { + plaintext: { + if outcome.is_ok() { + Some(plaintext) + } else { + None + } + }, + }) } } #[cfg(feature = "chacha8-poly1305")] -impl Encrypt for super::Chacha8Poly1305 -{ +impl Encrypt for super::Chacha8Poly1305 { #[inline(never)] - fn encrypt(keystore: &mut impl Keystore, request: &request::Encrypt) - -> Result - { - use chacha20poly1305::ChaCha8Poly1305; + fn encrypt( + keystore: &mut impl Keystore, + request: &request::Encrypt, + ) -> Result { use chacha20poly1305::aead::{AeadInPlace, NewAead}; - + use chacha20poly1305::ChaCha8Poly1305; // load key and nonce let secrecy = key::Secrecy::Secret; let key_kind = key::Kind::Symmetric32Nonce(12); let key_id = &request.key; - let mut serialized_material = keystore - .load_key(secrecy, Some(key_kind), key_id)? - .material; + let mut serialized_material = keystore.load_key(secrecy, Some(key_kind), key_id)?.material; let serialized: &mut [u8] = serialized_material.as_mut(); assert!(serialized.len() == 44); @@ -141,38 +143,44 @@ impl Encrypt for super::Chacha8Poly1305 None => generated_nonce, }; - - // keep in state? let aead = ChaCha8Poly1305::new(&GenericArray::clone_from_slice(symmetric_key)); let mut ciphertext = request.message.clone(); - let tag: [u8; 16] = aead.encrypt_in_place_detached( - &GenericArray::clone_from_slice(nonce), - &request.associated_data, - &mut ciphertext, - ).unwrap().as_slice().try_into().unwrap(); + let tag: [u8; 16] = aead + .encrypt_in_place_detached( + &GenericArray::clone_from_slice(nonce), + &request.associated_data, + &mut ciphertext, + ) + .unwrap() + .as_slice() + .try_into() + .unwrap(); let nonce = ShortData::from_slice(nonce).unwrap(); let tag = ShortData::from_slice(&tag).unwrap(); // let ciphertext = Message::from_slice(&ciphertext).unwrap(); - Ok(reply::Encrypt { ciphertext, nonce, tag }) + Ok(reply::Encrypt { + ciphertext, + nonce, + tag, + }) } } #[cfg(feature = "chacha8-poly1305")] -impl WrapKey for super::Chacha8Poly1305 -{ +impl WrapKey for super::Chacha8Poly1305 { #[inline(never)] - fn wrap_key(keystore: &mut impl Keystore, request: &request::WrapKey) - -> Result - { + fn wrap_key( + keystore: &mut impl Keystore, + request: &request::WrapKey, + ) -> Result { debug!("trussed: Chacha8Poly1305::WrapKey"); // TODO: need to check both secret and private keys - let serialized_key = keystore - .load_key(key::Secrecy::Secret, None, &request.key)?; + let serialized_key = keystore.load_key(key::Secrecy::Secret, None, &request.key)?; let message = Message::from_slice(&serialized_key.serialize()).unwrap(); @@ -185,21 +193,25 @@ impl WrapKey for super::Chacha8Poly1305 }; let encryption_reply = ::encrypt(keystore, &encryption_request)?; - let wrapped_key = crate::postcard_serialize_bytes(&encryption_reply).map_err(|_| Error::CborError)?; + let wrapped_key = + crate::postcard_serialize_bytes(&encryption_reply).map_err(|_| Error::CborError)?; Ok(reply::WrapKey { wrapped_key }) } } #[cfg(feature = "chacha8-poly1305")] -impl UnwrapKey for super::Chacha8Poly1305 -{ +impl UnwrapKey for super::Chacha8Poly1305 { #[inline(never)] - fn unwrap_key(keystore: &mut impl Keystore, request: &request::UnwrapKey) - -> Result - { - let reply::Encrypt { ciphertext, nonce, tag } = crate::postcard_deserialize( - &request.wrapped_key).map_err(|_| Error::CborError)?; + fn unwrap_key( + keystore: &mut impl Keystore, + request: &request::UnwrapKey, + ) -> Result { + let reply::Encrypt { + ciphertext, + nonce, + tag, + } = crate::postcard_deserialize(&request.wrapped_key).map_err(|_| Error::CborError)?; let decryption_request = request::Decrypt { mechanism: Mechanism::Chacha8Poly1305, @@ -211,14 +223,19 @@ impl UnwrapKey for super::Chacha8Poly1305 }; let serialized_key = if let Some(serialized_key) = - ::decrypt(keystore, &decryption_request)?.plaintext { + ::decrypt(keystore, &decryption_request)?.plaintext + { serialized_key } else { - return Ok(reply::UnwrapKey { key: None } ); + return Ok(reply::UnwrapKey { key: None }); }; // TODO: probably change this to returning Option too - let key::Key{ flags: _, kind, material } = key::Key::try_deserialize(&serialized_key)?; + let key::Key { + flags: _, + kind, + material, + } = key::Key::try_deserialize(&serialized_key)?; // TODO: need to check both secret and private keys let key_id = keystore.store_key( @@ -265,7 +282,6 @@ impl UnwrapKey for super::Chacha8Poly1305 // // ).map_err(|_| Error::AeadError) // // } - // #[cfg(feature = "chacha8-poly1305")] // impl // Decrypt

for super::Chacha8Poly1305 @@ -386,13 +402,9 @@ impl UnwrapKey for super::Chacha8Poly1305 // // ).map_err(|_| Error::AeadError) // // } - #[cfg(not(feature = "chacha8-poly1305"))] -impl -Decrypt

for super::Chacha8Poly1305 {} +impl Decrypt

for super::Chacha8Poly1305 {} #[cfg(not(feature = "chacha8-poly1305"))] -impl -Encrypt

for super::Chacha8Poly1305 {} +impl Encrypt

for super::Chacha8Poly1305 {} #[cfg(not(feature = "chacha8-poly1305"))] -impl -GenerateKey

for super::Chacha8Poly1305 {} +impl GenerateKey

for super::Chacha8Poly1305 {} diff --git a/src/mechanisms/ed255.rs b/src/mechanisms/ed255.rs index 21f9c4500c3..acced9124f5 100644 --- a/src/mechanisms/ed255.rs +++ b/src/mechanisms/ed255.rs @@ -7,28 +7,30 @@ use crate::error::Error; use crate::service::*; use crate::types::*; - #[inline(never)] -fn load_public_key(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result { - +#[inline(never)] +fn load_public_key( + keystore: &mut impl Keystore, + key_id: &KeyId, +) -> Result { let public_bytes: [u8; 32] = keystore .load_key(key::Secrecy::Public, Some(key::Kind::Ed255), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; - let public_key = salty::signature::PublicKey::try_from(&public_bytes).map_err(|_| Error::InternalError)?; + let public_key = + salty::signature::PublicKey::try_from(&public_bytes).map_err(|_| Error::InternalError)?; Ok(public_key) } - #[inline(never)] -fn load_keypair(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result { - +#[inline(never)] +fn load_keypair(keystore: &mut impl Keystore, key_id: &KeyId) -> Result { let seed: [u8; 32] = keystore .load_key(key::Secrecy::Secret, Some(key::Kind::Ed255), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; @@ -38,36 +40,36 @@ fn load_keypair(keystore: &mut impl Keystore, key_id: &KeyId) } #[cfg(feature = "ed255")] -impl DeriveKey for super::Ed255 -{ +impl DeriveKey for super::Ed255 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { let base_id = &request.base_key; let keypair = load_keypair(keystore, base_id)?; let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::Ed255, - keypair.public.as_bytes())?; + key::Secrecy::Public, + key::Kind::Ed255, + keypair.public.as_bytes(), + )?; - Ok(reply::DeriveKey { - key: public_id, - }) + Ok(reply::DeriveKey { key: public_id }) } } #[cfg(feature = "ed255")] -impl DeserializeKey for super::Ed255 -{ +impl DeserializeKey for super::Ed255 { #[inline(never)] - fn deserialize_key(keystore: &mut impl Keystore, request: &request::DeserializeKey) - -> Result - { - // - mechanism: Mechanism - // - serialized_key: Message - // - attributes: StorageAttributes + fn deserialize_key( + keystore: &mut impl Keystore, + request: &request::DeserializeKey, + ) -> Result { + // - mechanism: Mechanism + // - serialized_key: Message + // - attributes: StorageAttributes if request.format != KeySerialization::Raw { return Err(Error::InternalError); @@ -83,22 +85,22 @@ impl DeserializeKey for super::Ed255 let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::Ed255, - public_key.as_bytes())?; + key::Secrecy::Public, + key::Kind::Ed255, + public_key.as_bytes(), + )?; - Ok(reply::DeserializeKey { - key: public_id - }) + Ok(reply::DeserializeKey { key: public_id }) } } #[cfg(feature = "ed255")] -impl GenerateKey for super::Ed255 -{ +impl GenerateKey for super::Ed255 { #[inline(never)] - fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey) - -> Result - { + fn generate_key( + keystore: &mut impl Keystore, + request: &request::GenerateKey, + ) -> Result { let mut seed = [0u8; 32]; keystore.rng().fill_bytes(&mut seed); @@ -111,7 +113,8 @@ impl GenerateKey for super::Ed255 request.attributes.persistence, key::Secrecy::Secret, key::Info::from(key::Kind::Ed255).with_local_flag(), - &seed)?; + &seed, + )?; // return handle Ok(reply::GenerateKey { key: key_id }) @@ -119,12 +122,12 @@ impl GenerateKey for super::Ed255 } #[cfg(feature = "ed255")] -impl SerializeKey for super::Ed255 -{ +impl SerializeKey for super::Ed255 { #[inline(never)] - fn serialize_key(keystore: &mut impl Keystore, request: &request::SerializeKey) - -> Result - { + fn serialize_key( + keystore: &mut impl Keystore, + request: &request::SerializeKey, + ) -> Result { let key_id = request.key; let public_key = load_public_key(keystore, &key_id)?; @@ -140,12 +143,16 @@ impl SerializeKey for super::Ed255 KeySerialization::Raw => { let mut serialized_key = Message::new(); - serialized_key.extend_from_slice(public_key.as_bytes()).map_err(|_| Error::InternalError)?; + serialized_key + .extend_from_slice(public_key.as_bytes()) + .map_err(|_| Error::InternalError)?; // serialized_key.extend_from_slice(&buf).map_err(|_| Error::InternalError)?; serialized_key } - _ => { return Err(Error::InternalError); } + _ => { + return Err(Error::InternalError); + } }; Ok(reply::SerializeKey { serialized_key }) @@ -153,12 +160,12 @@ impl SerializeKey for super::Ed255 } #[cfg(feature = "ed255")] -impl Exists for super::Ed255 -{ +impl Exists for super::Ed255 { #[inline(never)] - fn exists(keystore: &mut impl Keystore, request: &request::Exists) - -> Result - { + fn exists( + keystore: &mut impl Keystore, + request: &request::Exists, + ) -> Result { let key_id = request.key; let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::Ed255), &key_id); @@ -167,12 +174,9 @@ impl Exists for super::Ed255 } #[cfg(feature = "ed255")] -impl Sign for super::Ed255 -{ +impl Sign for super::Ed255 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { // Not so nice, expands to // `trussed::/home/nicolas/projects/solo-bee/components/trussed/src/mechanisms/ed255.rs:151 // Ed255::Sign`, i.e. VEERY long @@ -196,17 +200,19 @@ impl Sign for super::Ed255 // hprintln!("sig: {:?}", &our_signature).ok(); // return signature - Ok(reply::Sign { signature: our_signature }) + Ok(reply::Sign { + signature: our_signature, + }) } } #[cfg(feature = "ed255")] -impl Verify for super::Ed255 -{ +impl Verify for super::Ed255 { #[inline(never)] - fn verify(keystore: &mut impl Keystore, request: &request::Verify) - -> Result - { + fn verify( + keystore: &mut impl Keystore, + request: &request::Verify, + ) -> Result { if let SignatureSerialization::Raw = request.format { } else { return Err(Error::InvalidSerializationFormat); @@ -223,8 +229,10 @@ impl Verify for super::Ed255 signature_array.copy_from_slice(request.signature.as_ref()); let salty_signature = salty::signature::Signature::from(&signature_array); - Ok(reply::Verify { valid: - public_key.verify(&request.message, &salty_signature).is_ok() + Ok(reply::Verify { + valid: public_key + .verify(&request.message, &salty_signature) + .is_ok(), }) } } diff --git a/src/mechanisms/hmacblake2s.rs b/src/mechanisms/hmacblake2s.rs index a9b62140682..833fb7bd5d1 100644 --- a/src/mechanisms/hmacblake2s.rs +++ b/src/mechanisms/hmacblake2s.rs @@ -1,21 +1,22 @@ - use crate::api::*; use crate::error::Error; use crate::service::*; use crate::types::*; #[cfg(feature = "hmac-blake2s")] -impl DeriveKey for super::HmacBlake2s -{ +impl DeriveKey for super::HmacBlake2s { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { use hmac::{Hmac, Mac, NewMac}; type HmacBlake2s = Hmac; let key_id = request.base_key.object_id; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; let mut mac = HmacBlake2s::new_from_slice(&shared_secret.as_ref()) .map_err(|_| Error::InternalError)?; @@ -23,30 +24,36 @@ impl DeriveKey for super::HmacBlake2s if let Some(additional_data) = &request.additional_data { mac.update(&additional_data); } - let derived_key: [u8; 32] = mac.finalize().into_bytes().try_into().map_err(|_| Error::InternalError)?; + let derived_key: [u8; 32] = mac + .finalize() + .into_bytes() + .try_into() + .map_err(|_| Error::InternalError)?; let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Symmetric(32), - &derived_key)?; - - Ok(reply::DeriveKey { key: ObjectHandle { object_id: key_id } }) + key::Secrecy::Secret, + key::Kind::Symmetric(32), + &derived_key, + )?; + Ok(reply::DeriveKey { + key: ObjectHandle { object_id: key_id }, + }) } } #[cfg(feature = "hmac-blake2s")] -impl Sign for super::HmacBlake2s -{ +impl Sign for super::HmacBlake2s { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { use blake2::Blake2s; use hmac::{Hmac, Mac, NewMac}; type HmacBlake2s = Hmac; let key_id = request.key.object_id; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; let mut mac = HmacBlake2s::new_from_slice(&shared_secret.as_ref()) .map_err(|_| Error::InternalError)?; @@ -56,7 +63,6 @@ impl Sign for super::HmacBlake2s let signature = Signature::from_slice(&result.into_bytes()).unwrap(); Ok(reply::Sign { signature }) - } } diff --git a/src/mechanisms/hmacsha1.rs b/src/mechanisms/hmacsha1.rs index d668bd696d8..f25e6c17652 100644 --- a/src/mechanisms/hmacsha1.rs +++ b/src/mechanisms/hmacsha1.rs @@ -1,62 +1,66 @@ - use crate::api::*; use crate::error::Error; use crate::service::*; use crate::types::*; #[cfg(feature = "hmac-sha1")] -impl DeriveKey for super::HmacSha1 -{ +impl DeriveKey for super::HmacSha1 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { use hmac::{Hmac, Mac, NewMac}; type HmacSha1 = Hmac; let key_id = request.base_key; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha1::new_from_slice(shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha1::new_from_slice(shared_secret.as_ref()).map_err(|_| Error::InternalError)?; if let Some(additional_data) = &request.additional_data { mac.update(additional_data); } - let derived_key: [u8; 20] = mac.finalize().into_bytes().try_into().map_err(|_| Error::InternalError)?; + let derived_key: [u8; 20] = mac + .finalize() + .into_bytes() + .try_into() + .map_err(|_| Error::InternalError)?; let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Symmetric(20), - &derived_key)?; + key::Secrecy::Secret, + key::Kind::Symmetric(20), + &derived_key, + )?; Ok(reply::DeriveKey { key: key_id }) - } } #[cfg(feature = "hmac-sha1")] -impl Sign for super::HmacSha1 -{ +impl Sign for super::HmacSha1 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { - use sha1::Sha1; + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { use hmac::{Hmac, Mac, NewMac}; + use sha1::Sha1; type HmacSha1 = Hmac; let key_id = request.key; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha1::new_from_slice(shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha1::new_from_slice(shared_secret.as_ref()).map_err(|_| Error::InternalError)?; mac.update(&request.message); let result = mac.finalize(); let signature = Signature::from_slice(&result.into_bytes()).unwrap(); Ok(reply::Sign { signature }) - } } diff --git a/src/mechanisms/hmacsha256.rs b/src/mechanisms/hmacsha256.rs index 9fafe107ba2..1b312945da0 100644 --- a/src/mechanisms/hmacsha256.rs +++ b/src/mechanisms/hmacsha256.rs @@ -1,62 +1,66 @@ - use crate::api::*; use crate::error::Error; use crate::service::*; use crate::types::*; #[cfg(feature = "hmac-sha256")] -impl DeriveKey for super::HmacSha256 -{ +impl DeriveKey for super::HmacSha256 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { use hmac::{Hmac, Mac, NewMac}; type HmacSha256 = Hmac; let key_id = request.base_key; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha256::new_from_slice(shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha256::new_from_slice(shared_secret.as_ref()).map_err(|_| Error::InternalError)?; if let Some(additional_data) = &request.additional_data { mac.update(additional_data); } - let derived_key: [u8; 32] = mac.finalize().into_bytes().try_into().map_err(|_| Error::InternalError)?; + let derived_key: [u8; 32] = mac + .finalize() + .into_bytes() + .try_into() + .map_err(|_| Error::InternalError)?; let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Symmetric(32), - &derived_key)?; + key::Secrecy::Secret, + key::Kind::Symmetric(32), + &derived_key, + )?; Ok(reply::DeriveKey { key: key_id }) - } } #[cfg(feature = "hmac-sha256")] -impl Sign for super::HmacSha256 -{ +impl Sign for super::HmacSha256 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { - use sha2::Sha256; + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { use hmac::{Hmac, Mac, NewMac}; + use sha2::Sha256; type HmacSha256 = Hmac; let key_id = request.key; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha256::new_from_slice(shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha256::new_from_slice(shared_secret.as_ref()).map_err(|_| Error::InternalError)?; mac.update(&request.message); let result = mac.finalize(); let signature = Signature::from_slice(&result.into_bytes()).unwrap(); Ok(reply::Sign { signature }) - } } diff --git a/src/mechanisms/hmacsha512.rs b/src/mechanisms/hmacsha512.rs index d415d4c54da..7a97a32c680 100644 --- a/src/mechanisms/hmacsha512.rs +++ b/src/mechanisms/hmacsha512.rs @@ -4,62 +4,65 @@ use crate::service::*; use crate::types::*; #[cfg(feature = "hmac-sha512")] -impl DeriveKey for super::HmacSha512 -{ +impl DeriveKey for super::HmacSha512 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { use hmac::{Hmac, Mac, NewMac}; type HmacSha512 = Hmac; let key_id = request.base_key.object_id; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha512::new_varkey(&shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha512::new_varkey(&shared_secret.as_ref()).map_err(|_| Error::InternalError)?; if let Some(additional_data) = &request.additional_data { mac.update(&additional_data); } let mut derived_key = [0u8; 64]; - derived_key.copy_from_slice(&mac.finalize().into_bytes());//.try_into().map_err(|_| Error::InternalError)?; + derived_key.copy_from_slice(&mac.finalize().into_bytes()); //.try_into().map_err(|_| Error::InternalError)?; let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Symmetric(64), - &derived_key)?; + key::Secrecy::Secret, + key::Kind::Symmetric(64), + &derived_key, + )?; - Ok(reply::DeriveKey { key: ObjectHandle { object_id: key_id } }) + Ok(reply::DeriveKey { + key: ObjectHandle { object_id: key_id }, + }) } } #[cfg(feature = "hmac-sha512")] -impl Sign for super::HmacSha512 -{ +impl Sign for super::HmacSha512 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { - use sha2::Sha512; + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { use hmac::{Hmac, Mac, NewMac}; + use sha2::Sha512; type HmacSha512 = Hmac; let key_id = request.key.object_id; - let shared_secret = keystore.load_key(key::Secrecy::Secret, None, &key_id)?.material; + let shared_secret = keystore + .load_key(key::Secrecy::Secret, None, &key_id)? + .material; - let mut mac = HmacSha512::new_varkey(&shared_secret.as_ref()) - .map_err(|_| Error::InternalError)?; + let mut mac = + HmacSha512::new_varkey(&shared_secret.as_ref()).map_err(|_| Error::InternalError)?; mac.update(&request.message); let result = mac.finalize(); let signature = Signature::from_slice(&result.into_bytes()).unwrap(); Ok(reply::Sign { signature }) - } } - #[cfg(not(feature = "hmac-sha512"))] impl DeriveKey for super::HmacSha512 {} #[cfg(not(feature = "hmac-sha512"))] diff --git a/src/mechanisms/p256.rs b/src/mechanisms/p256.rs index d79372c9df7..818b045295c 100644 --- a/src/mechanisms/p256.rs +++ b/src/mechanisms/p256.rs @@ -6,29 +6,32 @@ use crate::service::*; use crate::types::*; #[inline(never)] -fn load_secret_key(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result -{ - +fn load_secret_key( + keystore: &mut impl Keystore, + key_id: &KeyId, +) -> Result { // info_now!("loading keypair"); let secret_scalar: [u8; 32] = keystore .load_key(key::Secrecy::Secret, Some(key::Kind::P256), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; - let secret_key = p256_cortex_m4::SecretKey::from_bytes(&secret_scalar) - .map_err(|_| Error::InternalError)?; + let secret_key = + p256_cortex_m4::SecretKey::from_bytes(&secret_scalar).map_err(|_| Error::InternalError)?; Ok(secret_key) } #[inline(never)] -fn load_public_key(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result -{ +fn load_public_key( + keystore: &mut impl Keystore, + key_id: &KeyId, +) -> Result { let compressed_public_key: [u8; 33] = keystore .load_key(key::Secrecy::Public, Some(key::Kind::P256), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; @@ -37,12 +40,12 @@ fn load_public_key(keystore: &mut impl Keystore, key_id: &KeyId) } #[cfg(feature = "p256")] -impl Agree for super::P256 -{ +impl Agree for super::P256 { #[inline(never)] - fn agree(keystore: &mut impl Keystore, request: &request::Agree) - -> Result - { + fn agree( + keystore: &mut impl Keystore, + request: &request::Agree, + ) -> Result { let private_id = request.private_key; let public_id = request.public_key; @@ -53,21 +56,25 @@ impl Agree for super::P256 let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Shared(32), - shared_secret.as_bytes())?; + key::Secrecy::Secret, + key::Kind::Shared(32), + shared_secret.as_bytes(), + )?; // return handle - Ok(reply::Agree { shared_secret: key_id }) + Ok(reply::Agree { + shared_secret: key_id, + }) } } #[cfg(feature = "p256")] -impl DeriveKey for super::P256 -{ +impl DeriveKey for super::P256 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { let base_id = request.base_key; let secret_key = load_secret_key(keystore, &base_id)?; @@ -75,31 +82,32 @@ impl DeriveKey for super::P256 let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::P256, - &public_key.to_compressed_sec1_bytes())?; + key::Secrecy::Public, + key::Kind::P256, + &public_key.to_compressed_sec1_bytes(), + )?; - Ok(reply::DeriveKey { - key: public_id - }) + Ok(reply::DeriveKey { key: public_id }) } } #[cfg(feature = "p256")] -impl DeserializeKey for super::P256 -{ +impl DeserializeKey for super::P256 { #[inline(never)] - fn deserialize_key(keystore: &mut impl Keystore, request: &request::DeserializeKey) - -> Result - { - // - mechanism: Mechanism - // - serialized_key: Message - // - attributes: StorageAttributes + fn deserialize_key( + keystore: &mut impl Keystore, + request: &request::DeserializeKey, + ) -> Result { + // - mechanism: Mechanism + // - serialized_key: Message + // - attributes: StorageAttributes let public_key = match request.format { KeySerialization::Cose => { // TODO: this should all be done upstream - let cose_public_key: cosey::P256PublicKey = crate::cbor_deserialize( - &request.serialized_key).map_err(|_| Error::CborError)?; + let cose_public_key: cosey::P256PublicKey = + crate::cbor_deserialize(&request.serialized_key) + .map_err(|_| Error::CborError)?; let mut serialized_key = [0u8; 64]; if cose_public_key.x.len() != 32 || cose_public_key.y.len() != 32 { return Err(Error::InvalidSerializedKey); @@ -114,8 +122,9 @@ impl DeserializeKey for super::P256 KeySerialization::EcdhEsHkdf256 => { // TODO: this should all be done upstream - let cose_public_key: cosey::EcdhEsHkdf256PublicKey = crate::cbor_deserialize( - &request.serialized_key).map_err(|_| Error::CborError)?; + let cose_public_key: cosey::EcdhEsHkdf256PublicKey = + crate::cbor_deserialize(&request.serialized_key) + .map_err(|_| Error::CborError)?; let mut serialized_key = [0u8; 64]; if cose_public_key.x.len() != 32 || cose_public_key.y.len() != 32 { return Err(Error::InvalidSerializedKey); @@ -140,26 +149,29 @@ impl DeserializeKey for super::P256 .map_err(|_| Error::InvalidSerializedKey)? } - _ => { return Err(Error::InternalError); } + _ => { + return Err(Error::InternalError); + } }; let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::P256, - &public_key.to_compressed_sec1_bytes())?; - + key::Secrecy::Public, + key::Kind::P256, + &public_key.to_compressed_sec1_bytes(), + )?; Ok(reply::DeserializeKey { key: public_id }) } } #[cfg(feature = "p256")] -impl GenerateKey for super::P256 -{ +impl GenerateKey for super::P256 { #[inline(never)] - fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey) - -> Result - { + fn generate_key( + keystore: &mut impl Keystore, + request: &request::GenerateKey, + ) -> Result { let keypair = p256_cortex_m4::Keypair::random(&mut keystore.rng()); // store keys @@ -167,23 +179,21 @@ impl GenerateKey for super::P256 request.attributes.persistence, key::Secrecy::Secret, key::Info::from(key::Kind::P256).with_local_flag(), - &unsafe { keypair.secret.to_bytes() }, + &unsafe { keypair.secret.to_bytes() }, )?; // return handle Ok(reply::GenerateKey { key: key_id }) } - } #[cfg(feature = "p256")] -impl SerializeKey for super::P256 -{ +impl SerializeKey for super::P256 { #[inline(never)] - fn serialize_key(keystore: &mut impl Keystore, request: &request::SerializeKey) - -> Result - { - + fn serialize_key( + keystore: &mut impl Keystore, + request: &request::SerializeKey, + ) -> Result { let key_id = request.key; let public_key = load_public_key(keystore, &key_id)?; @@ -205,13 +215,19 @@ impl SerializeKey for super::P256 } KeySerialization::Raw => { let mut serialized_key = Message::new(); - serialized_key.extend_from_slice(&public_key.x()).map_err(|_| Error::InternalError)?; - serialized_key.extend_from_slice(&public_key.y()).map_err(|_| Error::InternalError)?; + serialized_key + .extend_from_slice(&public_key.x()) + .map_err(|_| Error::InternalError)?; + serialized_key + .extend_from_slice(&public_key.y()) + .map_err(|_| Error::InternalError)?; serialized_key } KeySerialization::Sec1 => { let mut serialized_key = Message::new(); - serialized_key.extend_from_slice(&public_key.to_compressed_sec1_bytes()).map_err(|_| Error::InternalError)?; + serialized_key + .extend_from_slice(&public_key.to_compressed_sec1_bytes()) + .map_err(|_| Error::InternalError)?; serialized_key } }; @@ -221,12 +237,12 @@ impl SerializeKey for super::P256 } #[cfg(feature = "p256")] -impl Exists for super::P256 -{ +impl Exists for super::P256 { #[inline(never)] - fn exists(keystore: &mut impl Keystore, request: &request::Exists) - -> Result - { + fn exists( + keystore: &mut impl Keystore, + request: &request::Exists, + ) -> Result { let key_id = request.key; let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::P256), &key_id); Ok(reply::Exists { exists }) @@ -234,12 +250,9 @@ impl Exists for super::P256 } #[cfg(feature = "p256")] -impl Sign for super::P256 -{ +impl Sign for super::P256 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { let key_id = request.key; let secret_key = load_secret_key(keystore, &key_id)?; @@ -258,18 +271,16 @@ impl Sign for super::P256 }; // return signature - Ok(reply::Sign { signature: serialized_signature }) + Ok(reply::Sign { + signature: serialized_signature, + }) } - } #[cfg(feature = "p256")] -impl Sign for super::P256Prehashed -{ +impl Sign for super::P256Prehashed { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { let key_id = request.key; let secret_key = load_secret_key(keystore, &key_id)?; @@ -288,18 +299,19 @@ impl Sign for super::P256Prehashed }; // return signature - Ok(reply::Sign { signature: serialized_signature }) + Ok(reply::Sign { + signature: serialized_signature, + }) } - } #[cfg(feature = "p256")] -impl Verify for super::P256 -{ +impl Verify for super::P256 { #[inline(never)] - fn verify(keystore: &mut impl Keystore, request: &request::Verify) - -> Result - { + fn verify( + keystore: &mut impl Keystore, + request: &request::Verify, + ) -> Result { let key_id = request.key; let public_key = load_public_key(keystore, &key_id)?; @@ -315,7 +327,7 @@ impl Verify for super::P256 } let valid = public_key.verify(&request.message, &signature); - Ok(reply::Verify { valid } ) + Ok(reply::Verify { valid }) } } diff --git a/src/mechanisms/sha256.rs b/src/mechanisms/sha256.rs index fd9144172e5..f1c4e87a95c 100644 --- a/src/mechanisms/sha256.rs +++ b/src/mechanisms/sha256.rs @@ -4,12 +4,12 @@ use crate::service::*; use crate::types::*; #[cfg(feature = "sha256")] -impl DeriveKey for super::Sha256 -{ +impl DeriveKey for super::Sha256 { #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { let base_id = &request.base_key; let shared_secret = keystore @@ -24,20 +24,19 @@ impl DeriveKey for super::Sha256 let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Symmetric(32), - &symmetric_key)?; + key::Secrecy::Secret, + key::Kind::Symmetric(32), + &symmetric_key, + )?; Ok(reply::DeriveKey { key: key_id }) } } #[cfg(feature = "sha256")] -impl Hash for super::Sha256 -{ +impl Hash for super::Sha256 { #[inline(never)] - fn hash(_keystore: &mut impl Keystore, request: &request::Hash) - -> Result - { + fn hash(_keystore: &mut impl Keystore, request: &request::Hash) -> Result { use sha2::digest::Digest; let mut hash = sha2::Sha256::new(); hash.update(&request.message); @@ -45,7 +44,7 @@ impl Hash for super::Sha256 let mut hashed = ShortData::new(); hashed.extend_from_slice(&hash.finalize()).unwrap(); - Ok(reply::Hash { hash: hashed } ) + Ok(reply::Hash { hash: hashed }) } } diff --git a/src/mechanisms/tdes.rs b/src/mechanisms/tdes.rs index d1bd7feafef..f0cc77f0e22 100644 --- a/src/mechanisms/tdes.rs +++ b/src/mechanisms/tdes.rs @@ -14,53 +14,67 @@ use crate::service::*; use crate::types::*; #[cfg(feature = "tdes")] -impl Encrypt for super::Tdes -{ +impl Encrypt for super::Tdes { /// Encrypts a single block. Let's hope we don't have to support ECB!! #[inline(never)] - fn encrypt(keystore: &mut impl Keystore, request: &request::Encrypt) - -> Result - { - if request.message.len() != 8 { return Err(Error::WrongMessageLength); } + fn encrypt( + keystore: &mut impl Keystore, + request: &request::Encrypt, + ) -> Result { + if request.message.len() != 8 { + return Err(Error::WrongMessageLength); + } let key_id = request.key; let symmetric_key: [u8; 24] = keystore .load_key(key::Secrecy::Secret, None, &key_id)? - .material.as_slice().try_into() + .material + .as_slice() + .try_into() .map_err(|_| Error::InternalError)?; - let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key)); + let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key)); - let mut message = request.message.clone(); + let mut message = request.message.clone(); cipher.encrypt_block(GenericArray::from_mut_slice(&mut message)); - Ok(reply::Encrypt { ciphertext: message, nonce: Default::default(), tag: Default::default() }) + Ok(reply::Encrypt { + ciphertext: message, + nonce: Default::default(), + tag: Default::default(), + }) } } #[cfg(feature = "tdes")] -impl Decrypt for super::Tdes -{ +impl Decrypt for super::Tdes { /// Decrypts a single block. Let's hope we don't have to support ECB!! #[inline(never)] - fn decrypt(keystore: &mut impl Keystore, request: &request::Decrypt) - -> Result - { - if request.message.len() != 8 { return Err(Error::WrongMessageLength); } + fn decrypt( + keystore: &mut impl Keystore, + request: &request::Decrypt, + ) -> Result { + if request.message.len() != 8 { + return Err(Error::WrongMessageLength); + } let key_id = request.key; let symmetric_key: [u8; 24] = keystore .load_key(key::Secrecy::Secret, None, &key_id)? - .material.as_slice().try_into() + .material + .as_slice() + .try_into() .map_err(|_| Error::InternalError)?; - let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key)); + let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key)); let mut message = request.message.clone(); cipher.decrypt_block(GenericArray::from_mut_slice(&mut message)); - Ok(reply::Decrypt { plaintext: Some(message) }) + Ok(reply::Decrypt { + plaintext: Some(message), + }) } } diff --git a/src/mechanisms/totp.rs b/src/mechanisms/totp.rs index 9d09f91ab8a..5147022f122 100644 --- a/src/mechanisms/totp.rs +++ b/src/mechanisms/totp.rs @@ -1,4 +1,3 @@ - use crate::api::*; use crate::error::Error; use crate::service::*; @@ -9,12 +8,12 @@ const DIGITS: u32 = 6; // https://tools.ietf.org/html/rfc4226#section-5.3 - #[inline(never)] +#[inline(never)] fn hotp_raw(key: &[u8], counter: u64, digits: u32) -> u64 { hmac_and_truncate(key, &counter.to_be_bytes(), digits) } - #[inline(never)] +#[inline(never)] fn hmac_and_truncate(key: &[u8], message: &[u8], digits: u32) -> u64 { use hmac::{Hmac, Mac, NewMac}; // let mut hmac = Hmac::::new(GenericArray::from_slice(key)); @@ -43,12 +42,9 @@ fn dynamic_truncation(hs: &[u8]) -> u64 { } #[cfg(feature = "totp")] -impl Sign for super::Totp -{ +impl Sign for super::Totp { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) - -> Result - { + fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { let key_id = request.key; let secret = keystore @@ -63,25 +59,30 @@ impl Sign for super::Totp let totp_material: u64 = hotp_raw(&secret, timestamp, DIGITS); // return signature (encode as LE) - Ok(reply::Sign { signature: crate::Bytes::from_slice(totp_material.to_le_bytes().as_ref()).unwrap() }) + Ok(reply::Sign { + signature: crate::Bytes::from_slice(totp_material.to_le_bytes().as_ref()).unwrap(), + }) } } #[cfg(feature = "totp")] -impl Exists for super::Totp -{ +impl Exists for super::Totp { #[inline(never)] - fn exists(keystore: &mut impl Keystore, request: &request::Exists) - -> Result - { + fn exists( + keystore: &mut impl Keystore, + request: &request::Exists, + ) -> Result { let key_id = request.key; - let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::Symmetric(20)), &key_id); + let exists = keystore.exists_key( + key::Secrecy::Secret, + Some(key::Kind::Symmetric(20)), + &key_id, + ); Ok(reply::Exists { exists }) } } - #[cfg(test)] mod tests { use super::*; diff --git a/src/mechanisms/trng.rs b/src/mechanisms/trng.rs index a237d223879..91b38500923 100644 --- a/src/mechanisms/trng.rs +++ b/src/mechanisms/trng.rs @@ -3,11 +3,11 @@ use crate::error::Error; use crate::service::*; #[cfg(feature = "trng")] -impl GenerateKey for super::Trng -{ - fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey) - -> Result - { +impl GenerateKey for super::Trng { + fn generate_key( + keystore: &mut impl Keystore, + request: &request::GenerateKey, + ) -> Result { // generate entropy let mut entropy = [0u8; 32]; keystore.rng().fill_bytes(&mut entropy); @@ -17,9 +17,9 @@ impl GenerateKey for super::Trng request.attributes.persistence, key::Secrecy::Secret, key::Kind::Symmetric(32), - &entropy)?; + &entropy, + )?; Ok(reply::GenerateKey { key: key_id }) } } - diff --git a/src/mechanisms/x255.rs b/src/mechanisms/x255.rs index 37dd4b5d85c..75bb92eda15 100644 --- a/src/mechanisms/x255.rs +++ b/src/mechanisms/x255.rs @@ -9,26 +9,31 @@ use crate::types::*; use salty::agreement; -fn load_public_key(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result { - +fn load_public_key( + keystore: &mut impl Keystore, + key_id: &KeyId, +) -> Result { let public_bytes: [u8; 32] = keystore .load_key(key::Secrecy::Public, Some(key::Kind::X255), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; - let public_key = agreement::PublicKey::try_from(public_bytes).map_err(|_| Error::InternalError)?; + let public_key = + agreement::PublicKey::try_from(public_bytes).map_err(|_| Error::InternalError)?; Ok(public_key) } -fn load_secret_key(keystore: &mut impl Keystore, key_id: &KeyId) - -> Result { - +fn load_secret_key( + keystore: &mut impl Keystore, + key_id: &KeyId, +) -> Result { let seed: [u8; 32] = keystore .load_key(key::Secrecy::Secret, Some(key::Kind::X255), key_id)? - .material.as_slice() + .material + .as_slice() .try_into() .map_err(|_| Error::InternalError)?; @@ -37,41 +42,39 @@ fn load_secret_key(keystore: &mut impl Keystore, key_id: &KeyId) } #[cfg(feature = "x255")] -impl Agree for super::X255 -{ +impl Agree for super::X255 { // #[inline(never)] - fn agree(keystore: &mut impl Keystore, request: &request::Agree) - -> Result - { - let secret_key = load_secret_key( - keystore, - &request.private_key, - )?; + fn agree( + keystore: &mut impl Keystore, + request: &request::Agree, + ) -> Result { + let secret_key = load_secret_key(keystore, &request.private_key)?; - let public_key = load_public_key( - keystore, - &request.public_key, - )?; + let public_key = load_public_key(keystore, &request.public_key)?; let shared_secret = secret_key.agree(&public_key).to_bytes(); let key_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Secret, key::Kind::Shared(32), - &shared_secret)?; + key::Secrecy::Secret, + key::Kind::Shared(32), + &shared_secret, + )?; // return handle - Ok(reply::Agree { shared_secret: key_id }) + Ok(reply::Agree { + shared_secret: key_id, + }) } } #[cfg(feature = "x255")] -impl GenerateKey for super::X255 -{ +impl GenerateKey for super::X255 { // #[inline(never)] - fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey) - -> Result - { + fn generate_key( + keystore: &mut impl Keystore, + request: &request::GenerateKey, + ) -> Result { // generate keypair let mut seed = [0u8; 32]; keystore.rng().fill_bytes(&mut seed); @@ -81,7 +84,8 @@ impl GenerateKey for super::X255 request.attributes.persistence, key::Secrecy::Secret, key::Info::from(key::Kind::X255).with_local_flag(), - &seed)?; + &seed, + )?; // return handle Ok(reply::GenerateKey { key: key_id }) @@ -89,12 +93,12 @@ impl GenerateKey for super::X255 } #[cfg(feature = "x255")] -impl Exists for super::X255 -{ +impl Exists for super::X255 { // #[inline(never)] - fn exists(keystore: &mut impl Keystore, request: &request::Exists) - -> Result - { + fn exists( + keystore: &mut impl Keystore, + request: &request::Exists, + ) -> Result { let key_id = request.key; let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::X255), &key_id); Ok(reply::Exists { exists }) @@ -102,12 +106,12 @@ impl Exists for super::X255 } #[cfg(feature = "x255")] -impl DeriveKey for super::X255 -{ +impl DeriveKey for super::X255 { // #[inline(never)] - fn derive_key(keystore: &mut impl Keystore, request: &request::DeriveKey) - -> Result - { + fn derive_key( + keystore: &mut impl Keystore, + request: &request::DeriveKey, + ) -> Result { let base_id = request.base_key; let secret_key = load_secret_key(keystore, &base_id)?; @@ -116,30 +120,36 @@ impl DeriveKey for super::X255 let public_key_bytes = public_key.to_bytes(); let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::X255, - &public_key_bytes)?; + key::Secrecy::Public, + key::Kind::X255, + &public_key_bytes, + )?; Ok(reply::DeriveKey { key: public_id }) } } #[cfg(feature = "x255")] -impl SerializeKey for super::X255 -{ +impl SerializeKey for super::X255 { // #[inline(never)] - fn serialize_key(keystore: &mut impl Keystore, request: &request::SerializeKey) - -> Result - { + fn serialize_key( + keystore: &mut impl Keystore, + request: &request::SerializeKey, + ) -> Result { let key_id = request.key; let public_key = load_public_key(keystore, &key_id)?; let mut serialized_key = Message::new(); match request.format { KeySerialization::Raw => { - serialized_key.extend_from_slice(&public_key.to_bytes()).map_err(|_| Error::InternalError)?; + serialized_key + .extend_from_slice(&public_key.to_bytes()) + .map_err(|_| Error::InternalError)?; } - _ => { return Err(Error::InternalError); } + _ => { + return Err(Error::InternalError); + } } Ok(reply::SerializeKey { serialized_key }) @@ -147,15 +157,15 @@ impl SerializeKey for super::X255 } #[cfg(feature = "x255")] -impl DeserializeKey for super::X255 -{ +impl DeserializeKey for super::X255 { // #[inline(never)] - fn deserialize_key(keystore: &mut impl Keystore, request: &request::DeserializeKey) - -> Result - { - // - mechanism: Mechanism - // - serialized_key: Message - // - attributes: StorageAttributes + fn deserialize_key( + keystore: &mut impl Keystore, + request: &request::DeserializeKey, + ) -> Result { + // - mechanism: Mechanism + // - serialized_key: Message + // - attributes: StorageAttributes if request.format != KeySerialization::Raw { return Err(Error::InternalError); @@ -171,14 +181,15 @@ impl DeserializeKey for super::X255 let public_id = keystore.store_key( request.attributes.persistence, - key::Secrecy::Public, key::Kind::X255, - &public_key.to_bytes())?; + key::Secrecy::Public, + key::Kind::X255, + &public_key.to_bytes(), + )?; Ok(reply::DeserializeKey { key: public_id }) } } - #[cfg(not(feature = "x255"))] impl Agree for super::X255 {} #[cfg(not(feature = "x255"))] diff --git a/src/pipe.rs b/src/pipe.rs index 00708fd020c..745620e38cd 100644 --- a/src/pipe.rs +++ b/src/pipe.rs @@ -1,11 +1,10 @@ #![allow(clippy::transmute_ptr_to_ptr)] use interchange::Responder; -use crate::api::{Request, Reply}; +use crate::api::{Reply, Request}; use crate::error::Error; use crate::types::ClientId; - cfg_if::cfg_if! { if #[cfg(feature = "clients-12")] { @@ -59,7 +58,6 @@ cfg_if::cfg_if! { } } - // pub use interchange::TrussedInterchange; // TODO: The request pipe should block if there is an unhandled @@ -78,6 +76,3 @@ pub struct ServiceEndpoint { } // pub type ClientEndpoint = Requester; - - - diff --git a/src/platform.rs b/src/platform.rs index 6defff9eada..8f784c6cb2e 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -7,11 +7,10 @@ //! TODO: Currently, `Platform::R` lacks the `CryptoRng` bound. // pub use rand_core::{CryptoRng, RngCore}; -pub use rand_core::{CryptoRng, RngCore}; pub use crate::store::Store; -pub use crate::types::{ui, reboot}; pub use crate::types::consent; - +pub use crate::types::{reboot, ui}; +pub use rand_core::{CryptoRng, RngCore}; pub trait UserInterface { /// Check if the user has indicated their presence so as to give @@ -38,10 +37,10 @@ pub trait UserInterface { } /// Exit / reset the application - fn reboot (&mut self, to: reboot::To) -> ! { + fn reboot(&mut self, to: reboot::To) -> ! { let _ = to; loop { - continue + continue; } } @@ -67,50 +66,54 @@ pub unsafe trait Platform { } #[macro_export] -macro_rules! platform { ( +macro_rules! platform { + ( $PlatformName:ident, R: $Rng:ty, S: $Store:ty, UI: $UserInterface:ty, ) => { + /// Platform struct implemented `trussed::Platform`, generated + /// by a Trussed-supplied macro at call site, using the platform-specific + /// implementations of its components. + pub struct $PlatformName { + rng: $Rng, + store: $Store, + user_interface: $UserInterface, + } - /// Platform struct implemented `trussed::Platform`, generated - /// by a Trussed-supplied macro at call site, using the platform-specific - /// implementations of its components. - pub struct $PlatformName { - rng: $Rng, - store: $Store, - user_interface: $UserInterface, - } - - impl $PlatformName { - pub fn new(rng: $Rng, store: $Store, user_interface: $UserInterface) -> Self { - Self { rng, store, user_interface } + impl $PlatformName { + pub fn new(rng: $Rng, store: $Store, user_interface: $UserInterface) -> Self { + Self { + rng, + store, + user_interface, + } + } } - } - unsafe impl $crate::platform::Platform for $PlatformName { - type R = $Rng; - type S = $Store; - type UI = $UserInterface; + unsafe impl $crate::platform::Platform for $PlatformName { + type R = $Rng; + type S = $Store; + type UI = $UserInterface; - fn user_interface(&mut self) -> &mut Self::UI { - &mut self.user_interface - } + fn user_interface(&mut self) -> &mut Self::UI { + &mut self.user_interface + } - fn rng(&mut self) -> &mut Self::R { - &mut self.rng - } + fn rng(&mut self) -> &mut Self::R { + &mut self.rng + } - fn store(&self) -> Self::S { - self.store + fn store(&self) -> Self::S { + self.store + } } - } -}} + }; +} /// Trussed client will call this method when making a Trussed request. /// This is intended to trigger a secure context on the platform. pub trait Syscall { fn syscall(&mut self); } - diff --git a/src/service.rs b/src/service.rs index 21a6d0c0721..9bcc339ca69 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,26 +1,25 @@ -pub use rand_core::{RngCore, SeedableRng}; -use interchange::Responder; -use littlefs2::path::PathBuf; use chacha20::ChaCha8Rng; use heapless_bytes::Unsigned; +use interchange::Responder; +use littlefs2::path::PathBuf; +pub use rand_core::{RngCore, SeedableRng}; use crate::api::*; -use crate::Bytes; -use crate::platform::*; use crate::config::*; use crate::error::Error; pub use crate::key; use crate::mechanisms; +pub use crate::pipe::ServiceEndpoint; use crate::pipe::TrussedInterchange; +use crate::platform::*; pub use crate::store::{ - filestore::{ClientFilestore, Filestore, ReadDirState, ReadDirFilesState}, - certstore::{ClientCertstore, Certstore as _}, + certstore::{Certstore as _, ClientCertstore}, counterstore::{ClientCounterstore, Counterstore as _}, + filestore::{ClientFilestore, Filestore, ReadDirFilesState, ReadDirState}, keystore::{ClientKeystore, Keystore}, }; use crate::types::*; -pub use crate::pipe::ServiceEndpoint; - +use crate::Bytes; pub mod attest; @@ -54,7 +53,8 @@ rpc_trait! { } pub struct ServiceResources

-where P: Platform +where + P: Platform, { pub(crate) platform: P, // // Option? @@ -66,7 +66,6 @@ where P: Platform } impl ServiceResources

{ - pub fn new(platform: P) -> Self { Self { platform, @@ -78,8 +77,11 @@ impl ServiceResources

{ } } -pub struct Service

where P: Platform { - eps: Vec, +pub struct Service

+where + P: Platform, +{ + eps: Vec, resources: ServiceResources

, } @@ -87,7 +89,6 @@ pub struct Service

where P: Platform { unsafe impl Send for Service

{} impl ServiceResources

{ - #[inline(never)] pub fn reply_to(&mut self, client_id: PathBuf, request: &Request) -> Result { // TODO: what we want to do here is map an enum to a generic type @@ -120,10 +121,7 @@ impl ServiceResources

{ let counterstore = &mut counterstore; // prepare filestore, bound to client_id, for storage calls - let mut filestore: ClientFilestore = ClientFilestore::new( - client_id, - full_store, - ); + let mut filestore: ClientFilestore = ClientFilestore::new(client_id, full_store); let filestore = &mut filestore; debug_now!("TRUSSED {:?}", request); @@ -579,21 +577,18 @@ impl ServiceResources

{ /// Applies a splitting aka forking construction to the inner DRBG, /// returning an independent DRBG. pub fn rng(&mut self) -> Result { - // Check if our RNG is loaded. let mut rng = match self.rng_state.take() { Some(rng) => rng, None => { - let mut filestore: ClientFilestore = ClientFilestore::new( - PathBuf::from("trussed"), - self.platform.store(), - ); + let mut filestore: ClientFilestore = + ClientFilestore::new(PathBuf::from("trussed"), self.platform.store()); let path = PathBuf::from("rng-state.bin"); // Load previous seed, e.g., externally injected entropy on first run. // Else, default to zeros - will mix in new HW RNG entropy next - let mixin_seed = if ! filestore.exists(&path, Location::Internal) { + let mixin_seed = if !filestore.exists(&path, Location::Internal) { [0u8; 32] } else { // Use the last saved state. @@ -619,7 +614,9 @@ impl ServiceResources

{ // 1. First, draw fresh entropy from the HW TRNG. let mut entropy = [0u8; 32]; - self.platform.rng().try_fill_bytes(&mut entropy) + self.platform + .rng() + .try_fill_bytes(&mut entropy) .map_err(|_| Error::EntropyMalfunction)?; // 2. Mix into our previously stored seed. @@ -634,11 +631,13 @@ impl ServiceResources

{ // 4. Store freshly drawn seed for next boot. let mut seed_to_store = [0u8; 32]; rng.fill_bytes(&mut seed_to_store); - filestore.write(&path, Location::Internal, seed_to_store.as_ref()).unwrap(); + filestore + .write(&path, Location::Internal, seed_to_store.as_ref()) + .unwrap(); // 5. Finish Ok(rng) - }? + }?, }; // split off another DRBG @@ -647,30 +646,34 @@ impl ServiceResources

{ split_rng } - pub fn fill_random_bytes(&mut self, bytes: &mut[u8]) -> Result<(), Error> { + pub fn fill_random_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> { self.rng()?.fill_bytes(bytes); Ok(()) } - } impl Service

{ - pub fn new(platform: P) -> Self { let resources = ServiceResources::new(platform); - Self { eps: Vec::new(), resources } + Self { + eps: Vec::new(), + resources, + } } /// Add a new client, claiming one of the statically configured /// interchange pairs. #[allow(clippy::result_unit_err)] - pub fn try_new_client(&mut self, client_id: &str, syscall: S) - -> Result, ()> - { + pub fn try_new_client( + &mut self, + client_id: &str, + syscall: S, + ) -> Result, ()> { use interchange::Interchange; let (requester, responder) = TrussedInterchange::claim().ok_or(())?; let client_id = ClientId::from(client_id.as_bytes()); - self.add_endpoint(responder, client_id).map_err(|_service_endpoint| ())?; + self.add_endpoint(responder, client_id) + .map_err(|_service_endpoint| ())?; Ok(crate::client::ClientImplementation::new(requester, syscall)) } @@ -679,13 +682,15 @@ impl Service

{ /// (directly call self for processing). This method is only useful for single-threaded /// single-app runners. #[allow(clippy::result_unit_err)] - pub fn try_as_new_client(&mut self, client_id: &str) - -> Result>, ()> - { + pub fn try_as_new_client( + &mut self, + client_id: &str, + ) -> Result>, ()> { use interchange::Interchange; let (requester, responder) = TrussedInterchange::claim().ok_or(())?; let client_id = ClientId::from(client_id.as_bytes()); - self.add_endpoint(responder, client_id).map_err(|_service_endpoint| ())?; + self.add_endpoint(responder, client_id) + .map_err(|_service_endpoint| ())?; Ok(crate::client::ClientImplementation::new(requester, self)) } @@ -693,38 +698,44 @@ impl Service

{ /// Similar to [try_as_new_client][Service::try_as_new_client] except that the returning client owns the /// Service and is therefore `'static` #[allow(clippy::result_unit_err)] - pub fn try_into_new_client(mut self, client_id: &str) - -> Result>, ()> - { + pub fn try_into_new_client( + mut self, + client_id: &str, + ) -> Result>, ()> { use interchange::Interchange; let (requester, responder) = TrussedInterchange::claim().ok_or(())?; let client_id = ClientId::from(client_id.as_bytes()); - self.add_endpoint(responder, client_id).map_err(|_service_endpoint| ())?; + self.add_endpoint(responder, client_id) + .map_err(|_service_endpoint| ())?; Ok(crate::client::ClientImplementation::new(requester, self)) } - - pub fn add_endpoint(&mut self, interchange: Responder, client_id: ClientId) -> Result<(), ServiceEndpoint> { + pub fn add_endpoint( + &mut self, + interchange: Responder, + client_id: ClientId, + ) -> Result<(), ServiceEndpoint> { if client_id == PathBuf::from("trussed") { panic!("trussed is a reserved client ID"); } - self.eps.push(ServiceEndpoint { interchange, client_id }) + self.eps.push(ServiceEndpoint { + interchange, + client_id, + }) } pub fn set_seed_if_uninitialized(&mut self, seed: &[u8; 32]) { - - let mut filestore: ClientFilestore = ClientFilestore::new( - PathBuf::from("trussed"), - self.resources.platform.store(), - ); + let mut filestore: ClientFilestore = + ClientFilestore::new(PathBuf::from("trussed"), self.resources.platform.store()); let filestore = &mut filestore; let path = PathBuf::from("rng-state.bin"); if !filestore.exists(&path, Location::Internal) { - filestore.write(&path, Location::Internal, seed.as_ref()).unwrap(); + filestore + .write(&path, Location::Internal, seed.as_ref()) + .unwrap(); } - } // currently, this just blinks the green heartbeat LED (former toggle_red in app_rtic.rs) @@ -733,7 +744,8 @@ impl Service

{ // - generate more interesting LED visuals // - return "when" next to be called // - potentially read out button status and return "async" - pub fn update_ui(&mut self) /* -> u32 */ { + pub fn update_ui(&mut self) /* -> u32 */ + { self.resources.platform.user_interface().refresh(); } @@ -745,27 +757,49 @@ impl Service

{ for ep in eps.iter_mut() { if let Some(request) = ep.interchange.take_request() { - resources.platform.user_interface().set_status(ui::Status::Processing); + resources + .platform + .user_interface() + .set_status(ui::Status::Processing); // #[cfg(test)] println!("service got request: {:?}", &request); // resources.currently_serving = ep.client_id.clone(); let reply_result = resources.reply_to(ep.client_id.clone(), &request); - resources.platform.user_interface().set_status(ui::Status::Idle); + resources + .platform + .user_interface() + .set_status(ui::Status::Idle); ep.interchange.respond(&reply_result).ok(); - } } - debug_now!("I/E/V : {}/{}/{} >", - self.resources.platform.store().ifs().available_blocks().unwrap(), - self.resources.platform.store().efs().available_blocks().unwrap(), - self.resources.platform.store().vfs().available_blocks().unwrap(), + debug_now!( + "I/E/V : {}/{}/{} >", + self.resources + .platform + .store() + .ifs() + .available_blocks() + .unwrap(), + self.resources + .platform + .store() + .efs() + .available_blocks() + .unwrap(), + self.resources + .platform + .store() + .vfs() + .available_blocks() + .unwrap(), ); } } impl

crate::client::Syscall for &mut Service

-where P: Platform +where + P: Platform, { fn syscall(&mut self) { self.process(); @@ -773,7 +807,8 @@ where P: Platform } impl

crate::client::Syscall for Service

-where P: Platform +where + P: Platform, { fn syscall(&mut self) { self.process(); diff --git a/src/service/attest.rs b/src/service/attest.rs index e9cffae377c..d89c8294600 100644 --- a/src/service/attest.rs +++ b/src/service/attest.rs @@ -1,31 +1,35 @@ - -use flexiber::{Encodable, EncodableHeapless, Encoder, Length as BerLength, Result as BerResult, Tag, TaggedSlice, TaggedValue}; +use flexiber::{ + Encodable, EncodableHeapless, Encoder, Length as BerLength, Result as BerResult, Tag, + TaggedSlice, TaggedValue, +}; use hex_literal::hex; use rand_core::RngCore; use crate::{ - api::{ - request::Attest as AttestRequest, - request, - reply::Attest as AttestReply, - }, + api::{reply::Attest as AttestReply, request, request::Attest as AttestRequest}, error::Error, - key, - mechanisms, + key, mechanisms, service::{DeriveKey, SerializeKey, Sign}, store::certstore::Certstore, store::keystore::Keystore, - types::{KeyId, KeySerialization, Location, Mechanism, Message, SignatureSerialization, StorageAttributes}, + types::{ + KeyId, KeySerialization, Location, Mechanism, Message, SignatureSerialization, + StorageAttributes, + }, }; #[cfg(not(feature = "test-attestation-cert-ids"))] pub const ED255_ATTN_KEY: KeyId = KeyId::from_special(1); #[cfg(feature = "test-attestation-cert-ids")] -pub const ED255_ATTN_KEY: KeyId = KeyId(Id(u128::from_be_bytes([0x12,0xd2,0xa7,0xe4,0x03,0x55,0x21,0x42,0x99,0xf1,0x57,0x34,0xc5,0xd7,0xd0,0xe7]))); +pub const ED255_ATTN_KEY: KeyId = KeyId(Id(u128::from_be_bytes([ + 0x12, 0xd2, 0xa7, 0xe4, 0x03, 0x55, 0x21, 0x42, 0x99, 0xf1, 0x57, 0x34, 0xc5, 0xd7, 0xd0, 0xe7, +]))); #[cfg(not(feature = "test-attestation-cert-ids"))] pub const P256_ATTN_KEY: KeyId = KeyId::from_special(2); #[cfg(feature = "test-attestation-cert-ids")] -pub const P256_ATTN_KEY: KeyId = KeyId(Id(u128::from_be_bytes([0xc8,0xd6,0x77,0xa3,0x93,0x46,0xc9,0x8f,0xc8,0x5a,0xb0,0x5d,0x29,0xc5,0x75,0x32]))); +pub const P256_ATTN_KEY: KeyId = KeyId(Id(u128::from_be_bytes([ + 0xc8, 0xd6, 0x77, 0xa3, 0x93, 0x46, 0xc9, 0x8f, 0xc8, 0x5a, 0xb0, 0x5d, 0x29, 0xc5, 0x75, 0x32, +]))); #[inline(never)] pub fn try_attest( @@ -33,11 +37,7 @@ pub fn try_attest( certstore: &mut impl Certstore, keystore: &mut impl Keystore, request: &AttestRequest, -) - -> Result - -{ - +) -> Result { let signature_algorithm = SignatureAlgorithm::try_from(request.signing_mechanism)?; // 1. Construct the TBS Certificate @@ -73,9 +73,12 @@ pub fn try_attest( mechanism: Mechanism::Ed255, base_key: request.private_key, additional_data: None, - attributes: StorageAttributes { persistence: Location::Volatile }, + attributes: StorageAttributes { + persistence: Location::Volatile, + }, }, - )?.key; + )? + .key; let serialized_key = mechanisms::Ed255::serialize_key( keystore, &request::SerializeKey { @@ -83,11 +86,16 @@ pub fn try_attest( key: public_key, format: KeySerialization::Raw, }, - ).unwrap().serialized_key; + ) + .unwrap() + .serialized_key; keystore.delete_key(&public_key); SerializedSubjectPublicKey::Ed255( - serialized_key.as_ref().try_into().map_err(|_| Error::ImplementationError)? + serialized_key + .as_ref() + .try_into() + .map_err(|_| Error::ImplementationError)?, ) } @@ -98,9 +106,12 @@ pub fn try_attest( mechanism: Mechanism::P256, base_key: request.private_key, additional_data: None, - attributes: StorageAttributes { persistence: Location::Volatile }, + attributes: StorageAttributes { + persistence: Location::Volatile, + }, }, - )?.key; + )? + .key; let serialized_key = mechanisms::P256::serialize_key( keystore, &request::SerializeKey { @@ -108,11 +119,16 @@ pub fn try_attest( key: public_key, format: KeySerialization::Sec1, }, - ).unwrap().serialized_key; + ) + .unwrap() + .serialized_key; keystore.delete_key(&public_key); SerializedSubjectPublicKey::P256( - serialized_key.as_ref().try_into().map_err(|_| Error::ImplementationError)? + serialized_key + .as_ref() + .try_into() + .map_err(|_| Error::ImplementationError)?, ) } }; @@ -121,17 +137,25 @@ pub fn try_attest( version: Version::V3, serial: BigEndianInteger(serial.as_ref()), signature_algorithm, - issuer: Name::default().with_country(b"CH").with_organization("Trussed").with_state("Zurich"), + issuer: Name::default() + .with_country(b"CH") + .with_organization("Trussed") + .with_state("Zurich"), // validity: Validity { start: Datetime(b"20210313120000Z"), end: None }, - validity: Validity { start: Datetime(b"20210313120000Z"), end: None }, + validity: Validity { + start: Datetime(b"20210313120000Z"), + end: None, + }, // subject: Name::default(), subject: Name::default(), //.with_country(b"CH").with_organization("Trussed").with_state("Zurich"), subject_public_key_info: spki, }; - let message = Message::from(TaggedValue::new(Tag::SEQUENCE, &to_be_signed_certificate) - .to_heapless_vec() - .map_err(|_| Error::InternalError)?); + let message = Message::from( + TaggedValue::new(Tag::SEQUENCE, &to_be_signed_certificate) + .to_heapless_vec() + .map_err(|_| Error::InternalError)?, + ); // 2. sign the TBS Cert let signature = match signature_algorithm { @@ -144,20 +168,28 @@ pub fn try_attest( message, format: SignatureSerialization::Raw, }, - ).unwrap().signature; + ) + .unwrap() + .signature; SerializedSignature::Ed255(signature.as_ref().try_into().unwrap()) } - SignatureAlgorithm::P256 => { - SerializedSignature::P256(heapless_bytes::Bytes::from_slice(mechanisms::P256::sign( - attn_keystore, - &request::Sign { - mechanism: Mechanism::P256, - key: P256_ATTN_KEY, - message, - format: SignatureSerialization::Asn1Der, - }, - ).unwrap().signature.as_ref()).unwrap()) - } + SignatureAlgorithm::P256 => SerializedSignature::P256( + heapless_bytes::Bytes::from_slice( + mechanisms::P256::sign( + attn_keystore, + &request::Sign { + mechanism: Mechanism::P256, + key: P256_ATTN_KEY, + message, + format: SignatureSerialization::Asn1Der, + }, + ) + .unwrap() + .signature + .as_ref(), + ) + .unwrap(), + ), }; let mut leading_zero_signature = [0u8; 80]; @@ -165,13 +197,15 @@ pub fn try_attest( leading_zero_signature[1..][..l].copy_from_slice(signature.as_ref()); // 3. construct the entire DER-serialized cert - let certificate = Message::from(Certificate { - tbs_certificate: to_be_signed_certificate, - signature_algorithm, - signature: &leading_zero_signature[..l + 1], - } + let certificate = Message::from( + Certificate { + tbs_certificate: to_be_signed_certificate, + signature_algorithm, + signature: &leading_zero_signature[..l + 1], + } .to_heapless_vec() - .map_err(|_| Error::ImplementationError)?); + .map_err(|_| Error::ImplementationError)?, + ); let id = certstore.write_certificate(Location::Internal, &certificate)?; @@ -197,7 +231,6 @@ pub struct TbsCertificate<'l> { subject: Name<'l>, #[tlv(constructed, number = "0x10")] // SEQUENCE subject_public_key_info: SerializedSubjectPublicKey, - // optional // extensions: Extensions } @@ -210,7 +243,7 @@ pub struct Certificate<'l> { #[tlv(constructed, number = "0x10")] // SEQUENCE signature_algorithm: SignatureAlgorithm, #[tlv(number = "0x3", slice)] // BIT-STRING - signature: &'l [u8],//SerializedSignature, + signature: &'l [u8], //SerializedSignature, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -239,7 +272,6 @@ impl AsRef<[u8]> for SerializedSignature { // } as u8).into()) // } - // fn encode(&self, encoder: &mut Encoder<'_>) -> BerResult<()> { // // NB: BIT-STRING needs to have number of "unused bits" in first byte (we have none) // match self { @@ -283,7 +315,6 @@ impl Version { } impl Encodable for Version { - fn encoded_length(&self) -> BerResult { Ok((Self::ENCODING.len() as u8).into()) } @@ -299,7 +330,6 @@ impl Encodable for Version { pub struct BigEndianInteger<'a>(pub &'a [u8]); impl Encodable for BigEndianInteger<'_> { - fn encoded_length(&self) -> BerResult { let mut num = self.0; // leading zeros must be trimmed (except zero, see below) @@ -345,17 +375,18 @@ impl TryFrom for SignatureAlgorithm { // 1.2.840.10045.4.3.2 ecdsaWithSHA256 (ANSI X9.62 ECDSA algorithm with SHA256)) const P256_OID_ENCODING: &[u8] = &hex!("06 08 2A 86 48 CE 3D 04 03 02"); -const P256_PUB_ENCODING: &[u8] = &hex!("06 07 2A 86 48 CE 3D 02 01 06 08 2A 86 48 CE 3D 03 01 07"); +const P256_PUB_ENCODING: &[u8] = + &hex!("06 07 2A 86 48 CE 3D 02 01 06 08 2A 86 48 CE 3D 03 01 07"); // 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm) const ED255_OID_ENCODING: &[u8] = &hex!("06 03 2B 65 70"); impl Encodable for SignatureAlgorithm { - fn encoded_length(&self) -> BerResult { Ok((match self { SignatureAlgorithm::Ed255 => ED255_OID_ENCODING.len(), SignatureAlgorithm::P256 => P256_OID_ENCODING.len(), - } as u8).into()) + } as u8) + .into()) } fn encode(&self, encoder: &mut Encoder<'_>) -> BerResult<()> { @@ -376,7 +407,7 @@ pub struct Name<'l> { } #[derive(Clone, Copy, Encodable, Eq, PartialEq)] -#[tlv(constructed, number = "0x10")] // SEQUENCE = 0x10 +#[tlv(constructed, number = "0x10")] // SEQUENCE = 0x10 struct EncodedPart<'l> { #[tlv(number = "0x6")] // OBJECT_IDENTIFIER oid: &'l [u8], @@ -386,13 +417,22 @@ struct EncodedPart<'l> { impl<'l> Name<'l> { pub fn with_country(self, country: &[u8; 2]) -> Self { - Self { country: Some(*country), ..self } + Self { + country: Some(*country), + ..self + } } pub fn with_organization(self, organization: &'l str) -> Self { - Self { organization: Some(organization), ..self } + Self { + organization: Some(organization), + ..self + } } pub fn with_state(self, state: &'l str) -> Self { - Self { state: Some(state), ..self } + Self { + state: Some(state), + ..self + } } } @@ -446,8 +486,12 @@ pub enum Extension {} pub struct Extensions<'l>(&'l [Extension]); impl Encodable for Extensions<'_> { - fn encoded_length(&self) -> BerResult { Ok(0u8.into()) } - fn encode(&self, _encoder: &mut Encoder<'_>) -> BerResult<()> { Ok(()) } + fn encoded_length(&self) -> BerResult { + Ok(0u8.into()) + } + fn encode(&self, _encoder: &mut Encoder<'_>) -> BerResult<()> { + Ok(()) + } } pub struct ParsedDatetime { @@ -471,10 +515,19 @@ impl ParsedDatetime { hour <= 23, minute <= 59, second <= 59, - ].iter().all(|b| *b); + ] + .iter() + .all(|b| *b); if valid { - Some(Self { year, month, day, hour, minute, second }) + Some(Self { + year, + month, + day, + hour, + minute, + second, + }) } else { None } @@ -483,10 +536,14 @@ impl ParsedDatetime { pub fn to_bytes(&self) -> [u8; 15] { let mut buffer: heapless::Vec = Default::default(); buffer.resize_default(15).unwrap(); - core::fmt::write(&mut buffer, format_args!( - "{}{:02}{:02}{:02}{:02}{:02}Z", - self.year, self.month, self.day, self.hour, self.minute, self.second - )).unwrap(); + core::fmt::write( + &mut buffer, + format_args!( + "{}{:02}{:02}{:02}{:02}{:02}Z", + self.year, self.month, self.day, self.hour, self.minute, self.second + ), + ) + .unwrap(); let mut array = [0u8; 15]; array.copy_from_slice(&buffer); array @@ -495,7 +552,7 @@ impl ParsedDatetime { #[derive(Clone, Copy, Eq, PartialEq)] /// Encoded as "YYYYMMDDHHMMSSZ", encoding takes care of truncating YYYY to YY if necessary. -pub struct Datetime<'l> (&'l [u8]); +pub struct Datetime<'l>(&'l [u8]); impl Encodable for Datetime<'_> { fn encoded_length(&self) -> BerResult { @@ -505,7 +562,8 @@ impl Encodable for Datetime<'_> { // starting 2050: GeneralizedTime -> keep YYYY } else { 0x11u8 - }.into()) + } + .into()) } fn encode(&self, encoder: &mut Encoder<'_>) -> BerResult<()> { let tagged_slice = if &self.0[..4] < b"2050" { @@ -528,7 +586,11 @@ pub struct Validity<'l> { impl Encodable for Validity<'_> { fn encoded_length(&self) -> BerResult { // before 2050: UtcTime -> truncate YYYY to YY - self.start.encoded_length()? + self.end.unwrap_or(Datetime(b"99991231235959Z")).encoded_length()? + self.start.encoded_length()? + + self + .end + .unwrap_or(Datetime(b"99991231235959Z")) + .encoded_length()? } fn encode(&self, encoder: &mut Encoder<'_>) -> BerResult<()> { @@ -549,38 +611,26 @@ impl Encodable for SerializedSubjectPublicKey { Ok((match self { SerializedSubjectPublicKey::Ed255(_) => 0x2A, SerializedSubjectPublicKey::P256(_) => 0x39, - } as u8).into()) + } as u8) + .into()) } - fn encode(&self, encoder: &mut Encoder<'_>) -> BerResult<()> { // NB: BIT-STRING needs to have number of "unused bits" in first byte (we have none) match self { SerializedSubjectPublicKey::Ed255(pub_key) => { - encoder.encode(&TaggedSlice::from( - Tag::SEQUENCE, - ED255_OID_ENCODING, - )?)?; + encoder.encode(&TaggedSlice::from(Tag::SEQUENCE, ED255_OID_ENCODING)?)?; let mut leading_zero = [0u8; 33]; leading_zero[1..].copy_from_slice(pub_key.as_ref()); - encoder.encode(&TaggedSlice::from( - Tag::BIT_STRING, - &leading_zero, - )?) + encoder.encode(&TaggedSlice::from(Tag::BIT_STRING, &leading_zero)?) // encoder.encode(&flexiber } SerializedSubjectPublicKey::P256(pub_key) => { - encoder.encode(&TaggedSlice::from( - Tag::SEQUENCE, - P256_PUB_ENCODING, - )?)?; + encoder.encode(&TaggedSlice::from(Tag::SEQUENCE, P256_PUB_ENCODING)?)?; let mut leading_zero = [0u8; 34]; leading_zero[1..].copy_from_slice(pub_key.as_ref()); - encoder.encode(&TaggedSlice::from( - Tag::BIT_STRING, - &leading_zero, - )?) + encoder.encode(&TaggedSlice::from(Tag::BIT_STRING, &leading_zero)?) } } } @@ -720,14 +770,6 @@ impl Encodable for SerializedSubjectPublicKey { // pub parameters: Option> //} - - - - - - - - // This is from docs.rs/x509 (version 0.2.0) // pub fn tbs_certificate<'a, W: Write + 'a, Alg, PKI, O: Oid + 'a, N: heapless::ArrayLength + 'a>( @@ -757,4 +799,3 @@ impl Encodable for SerializedSubjectPublicKey { // extensions::<_, _, N>(exts), // )) // } - diff --git a/src/store.rs b/src/store.rs index 45924fe82a0..35af5b82a1f 100644 --- a/src/store.rs +++ b/src/store.rs @@ -67,12 +67,12 @@ //! - Alternative: subdirectory <==> RP hash, everything else in flat files //! - In any case need to "list dirs excluding . and .." or similar +use crate::error::Error; +use crate::types::*; #[allow(unused_imports)] #[cfg(feature = "semihosting")] use cortex_m_semihosting::hprintln; use littlefs2::path::Path; -use crate::error::Error; -use crate::types::*; pub mod certstore; pub mod counterstore; @@ -144,310 +144,340 @@ impl Fs { } #[macro_export] -macro_rules! store { ( +macro_rules! store { + ( $store:ident, Internal: $Ifs:ty, External: $Efs:ty, Volatile: $Vfs:ty ) => { - #[derive(Clone, Copy)] - pub struct $store { - // __: $crate::store::NotSendOrSync, - __: core::marker::PhantomData<*mut ()>, - } + #[derive(Clone, Copy)] + pub struct $store { + // __: $crate::store::NotSendOrSync, + __: core::marker::PhantomData<*mut ()>, + } - unsafe impl $crate::store::Store for $store { - type I = $Ifs; - type E = $Efs; - type V = $Vfs; + unsafe impl $crate::store::Store for $store { + type I = $Ifs; + type E = $Efs; + type V = $Vfs; - fn ifs(self) -> &'static $crate::store::Fs<$Ifs> { - unsafe { &*Self::ifs_ptr() } - } - fn efs(self) -> &'static $crate::store::Fs<$Efs> { - unsafe { &*Self::efs_ptr() } - } - fn vfs(self) -> &'static $crate::store::Fs<$Vfs> { - unsafe { &*Self::vfs_ptr() } + fn ifs(self) -> &'static $crate::store::Fs<$Ifs> { + unsafe { &*Self::ifs_ptr() } + } + fn efs(self) -> &'static $crate::store::Fs<$Efs> { + unsafe { &*Self::efs_ptr() } + } + fn vfs(self) -> &'static $crate::store::Fs<$Vfs> { + unsafe { &*Self::vfs_ptr() } + } } - } - impl $store { - #[allow(dead_code)] - pub fn allocate( - internal_fs: $Ifs, - external_fs: $Efs, - volatile_fs: $Vfs, - ) -> ( - &'static mut littlefs2::fs::Allocation<$Ifs>, - &'static mut $Ifs, - &'static mut littlefs2::fs::Allocation<$Efs>, - &'static mut $Efs, - &'static mut littlefs2::fs::Allocation<$Vfs>, - &'static mut $Vfs, - ) { - // static mut INTERNAL_STORAGE: $Ifs = i_ctor();//<$Ifs>::new(); - - static mut INTERNAL_STORAGE: Option<$Ifs> = None; - unsafe { INTERNAL_STORAGE = Some(internal_fs); } - static mut INTERNAL_FS_ALLOC: Option> = None; - unsafe { INTERNAL_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); } - - // static mut EXTERNAL_STORAGE: $Efs = <$Efs>::new(); - static mut EXTERNAL_STORAGE: Option<$Efs> = None; - unsafe { EXTERNAL_STORAGE = Some(external_fs); } - static mut EXTERNAL_FS_ALLOC: Option> = None; - unsafe { EXTERNAL_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); } - - // static mut VOLATILE_STORAGE: $Vfs = <$Vfs>::new(); - static mut VOLATILE_STORAGE: Option<$Vfs> = None; - unsafe { VOLATILE_STORAGE = Some(volatile_fs); } - static mut VOLATILE_FS_ALLOC: Option> = None; - unsafe { VOLATILE_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); } - - ( - unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, - - unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, - - unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, - unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, - ) - } + impl $store { + #[allow(dead_code)] + pub fn allocate( + internal_fs: $Ifs, + external_fs: $Efs, + volatile_fs: $Vfs, + ) -> ( + &'static mut littlefs2::fs::Allocation<$Ifs>, + &'static mut $Ifs, + &'static mut littlefs2::fs::Allocation<$Efs>, + &'static mut $Efs, + &'static mut littlefs2::fs::Allocation<$Vfs>, + &'static mut $Vfs, + ) { + // static mut INTERNAL_STORAGE: $Ifs = i_ctor();//<$Ifs>::new(); + + static mut INTERNAL_STORAGE: Option<$Ifs> = None; + unsafe { + INTERNAL_STORAGE = Some(internal_fs); + } + static mut INTERNAL_FS_ALLOC: Option> = None; + unsafe { + INTERNAL_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); + } - #[allow(dead_code)] - pub fn init( - internal_fs: $Ifs, - external_fs: $Efs, - volatile_fs: $Vfs, - format: bool, - ) - -> Self - { - let (ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage) = - Self::allocate(internal_fs, external_fs, volatile_fs); - let store = Self::claim().unwrap(); - store.mount(ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage, format).unwrap(); - - store - } + // static mut EXTERNAL_STORAGE: $Efs = <$Efs>::new(); + static mut EXTERNAL_STORAGE: Option<$Efs> = None; + unsafe { + EXTERNAL_STORAGE = Some(external_fs); + } + static mut EXTERNAL_FS_ALLOC: Option> = None; + unsafe { + EXTERNAL_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); + } - #[allow(dead_code)] - pub fn init_raw(ifs: &'static littlefs2::fs::Filesystem<$Ifs>, - efs: &'static littlefs2::fs::Filesystem<$Efs>, - vfs: &'static littlefs2::fs::Filesystem<$Vfs> - ) - -> Self - { - let store_ifs = $crate::store::Fs::new(ifs); - let store_efs = $crate::store::Fs::new(efs); - let store_vfs = $crate::store::Fs::new(vfs); - unsafe { - Self::ifs_ptr().write(store_ifs); - Self::efs_ptr().write(store_efs); - Self::vfs_ptr().write(store_vfs); + // static mut VOLATILE_STORAGE: $Vfs = <$Vfs>::new(); + static mut VOLATILE_STORAGE: Option<$Vfs> = None; + unsafe { + VOLATILE_STORAGE = Some(volatile_fs); + } + static mut VOLATILE_FS_ALLOC: Option> = None; + unsafe { + VOLATILE_FS_ALLOC = Some(littlefs2::fs::Filesystem::allocate()); + } + + ( + unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, + unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, + ) } - Self::claim().unwrap() - } - #[allow(dead_code)] - pub fn attach(internal_fs: $Ifs, external_fs: $Efs, volatile_fs: $Vfs) -> Self { - Self::init(internal_fs, external_fs, volatile_fs, false) - } + #[allow(dead_code)] + pub fn init( + internal_fs: $Ifs, + external_fs: $Efs, + volatile_fs: $Vfs, + format: bool, + ) -> Self { + let (ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage) = + Self::allocate(internal_fs, external_fs, volatile_fs); + let store = Self::claim().unwrap(); + store + .mount( + ifs_alloc, + ifs_storage, + efs_alloc, + efs_storage, + vfs_alloc, + vfs_storage, + format, + ) + .unwrap(); + + store + } - #[allow(dead_code)] - pub fn format(internal_fs: $Ifs, external_fs: $Efs, volatile_fs: $Vfs) -> Self { - Self::init(internal_fs, external_fs, volatile_fs, true) - } + #[allow(dead_code)] + pub fn init_raw( + ifs: &'static littlefs2::fs::Filesystem<$Ifs>, + efs: &'static littlefs2::fs::Filesystem<$Efs>, + vfs: &'static littlefs2::fs::Filesystem<$Vfs>, + ) -> Self { + let store_ifs = $crate::store::Fs::new(ifs); + let store_efs = $crate::store::Fs::new(efs); + let store_vfs = $crate::store::Fs::new(vfs); + unsafe { + Self::ifs_ptr().write(store_ifs); + Self::efs_ptr().write(store_efs); + Self::vfs_ptr().write(store_vfs); + } + Self::claim().unwrap() + } - pub fn claim() -> Option<$store> { - use core::sync::atomic::{AtomicBool, Ordering}; - // use $crate::store::NotSendOrSync; + #[allow(dead_code)] + pub fn attach(internal_fs: $Ifs, external_fs: $Efs, volatile_fs: $Vfs) -> Self { + Self::init(internal_fs, external_fs, volatile_fs, false) + } - static CLAIMED: AtomicBool = AtomicBool::new(false); + #[allow(dead_code)] + pub fn format(internal_fs: $Ifs, external_fs: $Efs, volatile_fs: $Vfs) -> Self { + Self::init(internal_fs, external_fs, volatile_fs, true) + } - if CLAIMED - .compare_exchange_weak(false, true, Ordering::AcqRel, Ordering::Acquire) - .is_ok() - { - // Some(Self { __: unsafe { $crate::store::NotSendOrSync::new() } }) - Some(Self { __: core::marker::PhantomData }) - } else { - None + pub fn claim() -> Option<$store> { + use core::sync::atomic::{AtomicBool, Ordering}; + // use $crate::store::NotSendOrSync; + + static CLAIMED: AtomicBool = AtomicBool::new(false); + + if CLAIMED + .compare_exchange_weak(false, true, Ordering::AcqRel, Ordering::Acquire) + .is_ok() + { + // Some(Self { __: unsafe { $crate::store::NotSendOrSync::new() } }) + Some(Self { + __: core::marker::PhantomData, + }) + } else { + None + } } - } - fn ifs_ptr() -> *mut $crate::store::Fs<$Ifs> { - use core::{mem::MaybeUninit}; - use $crate::store::Fs; - static mut IFS: MaybeUninit> = MaybeUninit::uninit(); - unsafe { IFS.as_mut_ptr() } - } + fn ifs_ptr() -> *mut $crate::store::Fs<$Ifs> { + use core::mem::MaybeUninit; + use $crate::store::Fs; + static mut IFS: MaybeUninit> = MaybeUninit::uninit(); + unsafe { IFS.as_mut_ptr() } + } - fn efs_ptr() -> *mut $crate::store::Fs<$Efs> { - use core::{mem::MaybeUninit}; - use $crate::store::Fs; - static mut EFS: MaybeUninit> = MaybeUninit::uninit(); - unsafe { EFS.as_mut_ptr() } - } + fn efs_ptr() -> *mut $crate::store::Fs<$Efs> { + use core::mem::MaybeUninit; + use $crate::store::Fs; + static mut EFS: MaybeUninit> = MaybeUninit::uninit(); + unsafe { EFS.as_mut_ptr() } + } - fn vfs_ptr() -> *mut $crate::store::Fs<$Vfs> { - use core::{mem::MaybeUninit}; - use $crate::store::Fs; - static mut VFS: MaybeUninit> = MaybeUninit::uninit(); - unsafe { VFS.as_mut_ptr() } - } + fn vfs_ptr() -> *mut $crate::store::Fs<$Vfs> { + use core::mem::MaybeUninit; + use $crate::store::Fs; + static mut VFS: MaybeUninit> = MaybeUninit::uninit(); + unsafe { VFS.as_mut_ptr() } + } - pub fn mount( - &self, - - ifs_alloc: &'static mut littlefs2::fs::Allocation<$Ifs>, - ifs_storage: &'static mut $Ifs, - efs_alloc: &'static mut littlefs2::fs::Allocation<$Efs>, - efs_storage: &'static mut $Efs, - vfs_alloc: &'static mut littlefs2::fs::Allocation<$Vfs>, - vfs_storage: &'static mut $Vfs, - - // statics: ( - // &'static mut littlefs2::fs::Allocation<$Ifs>, - // &'static mut $Ifs, - // &'static mut littlefs2::fs::Allocation<$Efs>, - // &'static mut $Efs, - // &'static mut littlefs2::fs::Allocation<$Vfs>, - // &'static mut $Vfs, - // ), - // TODO: flag per backend? - format: bool, - ) -> littlefs2::io::Result<()> { - - use core::{ - mem::MaybeUninit, - }; - use littlefs2::fs::{ - Allocation, - Filesystem, - }; - - static mut IFS_ALLOC: MaybeUninit<&'static mut Allocation<$Ifs>> = MaybeUninit::uninit(); - static mut IFS_STORAGE: MaybeUninit<&'static mut $Ifs> = MaybeUninit::uninit(); - static mut IFS: Option> = None; - - static mut EFS_ALLOC: MaybeUninit<&'static mut Allocation<$Efs>> = MaybeUninit::uninit(); - static mut EFS_STORAGE: MaybeUninit<&'static mut $Efs> = MaybeUninit::uninit(); - static mut EFS: Option> = None; - - static mut VFS_ALLOC: MaybeUninit<&'static mut Allocation<$Vfs>> = MaybeUninit::uninit(); - static mut VFS_STORAGE: MaybeUninit<&'static mut $Vfs> = MaybeUninit::uninit(); - static mut VFS: Option> = None; - - // let (ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage) = statics; - - unsafe { - // always need to format RAM - Filesystem::format(vfs_storage).expect("can format"); - // this is currently a RAM fs too... - Filesystem::format(efs_storage).expect("can format"); - - if format { - Filesystem::format(ifs_storage).expect("can format"); + pub fn mount( + &self, + + ifs_alloc: &'static mut littlefs2::fs::Allocation<$Ifs>, + ifs_storage: &'static mut $Ifs, + efs_alloc: &'static mut littlefs2::fs::Allocation<$Efs>, + efs_storage: &'static mut $Efs, + vfs_alloc: &'static mut littlefs2::fs::Allocation<$Vfs>, + vfs_storage: &'static mut $Vfs, + + // statics: ( + // &'static mut littlefs2::fs::Allocation<$Ifs>, + // &'static mut $Ifs, + // &'static mut littlefs2::fs::Allocation<$Efs>, + // &'static mut $Efs, + // &'static mut littlefs2::fs::Allocation<$Vfs>, + // &'static mut $Vfs, + // ), + // TODO: flag per backend? + format: bool, + ) -> littlefs2::io::Result<()> { + use core::mem::MaybeUninit; + use littlefs2::fs::{Allocation, Filesystem}; + + static mut IFS_ALLOC: MaybeUninit<&'static mut Allocation<$Ifs>> = + MaybeUninit::uninit(); + static mut IFS_STORAGE: MaybeUninit<&'static mut $Ifs> = MaybeUninit::uninit(); + static mut IFS: Option> = None; + + static mut EFS_ALLOC: MaybeUninit<&'static mut Allocation<$Efs>> = + MaybeUninit::uninit(); + static mut EFS_STORAGE: MaybeUninit<&'static mut $Efs> = MaybeUninit::uninit(); + static mut EFS: Option> = None; + + static mut VFS_ALLOC: MaybeUninit<&'static mut Allocation<$Vfs>> = + MaybeUninit::uninit(); + static mut VFS_STORAGE: MaybeUninit<&'static mut $Vfs> = MaybeUninit::uninit(); + static mut VFS: Option> = None; + + // let (ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage) = statics; + + unsafe { + // always need to format RAM + Filesystem::format(vfs_storage).expect("can format"); + // this is currently a RAM fs too... + Filesystem::format(efs_storage).expect("can format"); + + if format { + Filesystem::format(ifs_storage).expect("can format"); + } + + IFS_ALLOC.as_mut_ptr().write(ifs_alloc); + IFS_STORAGE.as_mut_ptr().write(ifs_storage); + IFS = Some(Filesystem::mount( + &mut *IFS_ALLOC.as_mut_ptr(), + &mut *IFS_STORAGE.as_mut_ptr(), + )?); + let ifs = $crate::store::Fs::new(IFS.as_ref().unwrap()); + Self::ifs_ptr().write(ifs); + + EFS_ALLOC.as_mut_ptr().write(efs_alloc); + EFS_STORAGE.as_mut_ptr().write(efs_storage); + EFS = Some(Filesystem::mount( + &mut *EFS_ALLOC.as_mut_ptr(), + &mut *EFS_STORAGE.as_mut_ptr(), + )?); + let efs = $crate::store::Fs::new(EFS.as_ref().unwrap()); + Self::efs_ptr().write(efs); + + VFS_ALLOC.as_mut_ptr().write(vfs_alloc); + VFS_STORAGE.as_mut_ptr().write(vfs_storage); + VFS = Some(Filesystem::mount( + &mut *VFS_ALLOC.as_mut_ptr(), + &mut *VFS_STORAGE.as_mut_ptr(), + )?); + let vfs = $crate::store::Fs::new(VFS.as_ref().unwrap()); + Self::vfs_ptr().write(vfs); + + Ok(()) } + } - IFS_ALLOC.as_mut_ptr().write(ifs_alloc); - IFS_STORAGE.as_mut_ptr().write(ifs_storage); - IFS = Some(Filesystem::mount( - &mut *IFS_ALLOC.as_mut_ptr(), - &mut *IFS_STORAGE.as_mut_ptr(), - )?); - let ifs = $crate::store::Fs::new(IFS.as_ref().unwrap()); - Self::ifs_ptr().write(ifs); - - EFS_ALLOC.as_mut_ptr().write(efs_alloc); - EFS_STORAGE.as_mut_ptr().write(efs_storage); - EFS = Some(Filesystem::mount( - &mut *EFS_ALLOC.as_mut_ptr(), - &mut *EFS_STORAGE.as_mut_ptr(), - )?); - let efs = $crate::store::Fs::new(EFS.as_ref().unwrap()); - Self::efs_ptr().write(efs); - - VFS_ALLOC.as_mut_ptr().write(vfs_alloc); - VFS_STORAGE.as_mut_ptr().write(vfs_storage); - VFS = Some(Filesystem::mount( - &mut *VFS_ALLOC.as_mut_ptr(), - &mut *VFS_STORAGE.as_mut_ptr(), - )?); - let vfs = $crate::store::Fs::new(VFS.as_ref().unwrap()); - Self::vfs_ptr().write(vfs); - - Ok(()) + #[allow(dead_code)] + pub fn attach_else_format( + internal_fs: $Ifs, + external_fs: $Efs, + volatile_fs: $Vfs, + ) -> Self { + // This unfortunately repeates the code of `allocate`. + // It seems Rust's borrowing rules go against this. + use littlefs2::fs::{Allocation, Filesystem}; + + static mut INTERNAL_STORAGE: Option<$Ifs> = None; + unsafe { + INTERNAL_STORAGE = Some(internal_fs); + } + static mut INTERNAL_FS_ALLOC: Option> = None; + unsafe { + INTERNAL_FS_ALLOC = Some(Filesystem::allocate()); + } - } - } + // static mut EXTERNAL_STORAGE: $Efs = <$Efs>::new(); + static mut EXTERNAL_STORAGE: Option<$Efs> = None; + unsafe { + EXTERNAL_STORAGE = Some(external_fs); + } + static mut EXTERNAL_FS_ALLOC: Option> = None; + unsafe { + EXTERNAL_FS_ALLOC = Some(Filesystem::allocate()); + } - #[allow(dead_code)] - pub fn attach_else_format(internal_fs: $Ifs, external_fs: $Efs, volatile_fs: $Vfs) -> Self { - // This unfortunately repeates the code of `allocate`. - // It seems Rust's borrowing rules go against this. - use littlefs2::fs::{ - Allocation, - Filesystem, - }; - - static mut INTERNAL_STORAGE: Option<$Ifs> = None; - unsafe { INTERNAL_STORAGE = Some(internal_fs); } - static mut INTERNAL_FS_ALLOC: Option> = None; - unsafe { INTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - - // static mut EXTERNAL_STORAGE: $Efs = <$Efs>::new(); - static mut EXTERNAL_STORAGE: Option<$Efs> = None; - unsafe { EXTERNAL_STORAGE = Some(external_fs); } - static mut EXTERNAL_FS_ALLOC: Option> = None; - unsafe { EXTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - - // static mut VOLATILE_STORAGE: $Vfs = <$Vfs>::new(); - static mut VOLATILE_STORAGE: Option<$Vfs> = None; - unsafe { VOLATILE_STORAGE = Some(volatile_fs); } - static mut VOLATILE_FS_ALLOC: Option> = None; - unsafe { VOLATILE_FS_ALLOC = Some(Filesystem::allocate()); } - - let store = Self::claim().unwrap(); - if store.mount( - unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, - - unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, - - unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, - unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, - false - ).is_err() { - store.mount( - unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, + // static mut VOLATILE_STORAGE: $Vfs = <$Vfs>::new(); + static mut VOLATILE_STORAGE: Option<$Vfs> = None; + unsafe { + VOLATILE_STORAGE = Some(volatile_fs); + } + static mut VOLATILE_FS_ALLOC: Option> = None; + unsafe { + VOLATILE_FS_ALLOC = Some(Filesystem::allocate()); + } - unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, + let store = Self::claim().unwrap(); + if store + .mount( + unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, + unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, + false, + ) + .is_err() + { + store + .mount( + unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { EXTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, + unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, + true, + ) + .unwrap(); + } - unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, - unsafe { VOLATILE_STORAGE.as_mut().unwrap() }, - true).unwrap(); + store } - - store } - - } -}} + }; +} // TODO: replace this with "fs.create_dir_all(path.parent())" pub fn create_directories<'s, S: LfsStorage>( fs: &Filesystem<'s, S>, path: &Path, -) -> Result<(), Error> -{ +) -> Result<(), Error> { // hprintln!("preparing {:?}", core::str::from_utf8(path).unwrap()).ok(); let path_bytes = path.as_ref().as_bytes(); @@ -461,7 +491,9 @@ pub fn create_directories<'s, S: LfsStorage>( match fs.create_dir(&dir) { Err(littlefs2::io::Error::EntryAlreadyExisted) => {} Ok(()) => {} - error => { panic!("{:?}", &error); } + error => { + panic!("{:?}", &error); + } } } } @@ -470,29 +502,46 @@ pub fn create_directories<'s, S: LfsStorage>( /// Reads contents from path in location of store. #[inline(never)] -pub fn read(store: impl Store, location: Location, path: &Path) -> Result, Error> { +pub fn read( + store: impl Store, + location: Location, + path: &Path, +) -> Result, Error> { debug_now!("reading {}", &path); match location { Location::Internal => store.ifs().read(path), Location::External => store.efs().read(path), Location::Volatile => store.vfs().read(path), - }.map(Bytes::from).map_err(|_| Error::FilesystemReadFailure) + } + .map(Bytes::from) + .map_err(|_| Error::FilesystemReadFailure) } /// Writes contents to path in location of store. #[inline(never)] -pub fn write(store: impl Store, location: Location, path: &Path, contents: &[u8]) -> Result<(), Error> { +pub fn write( + store: impl Store, + location: Location, + path: &Path, + contents: &[u8], +) -> Result<(), Error> { debug_now!("writing {}", &path); match location { Location::Internal => store.ifs().write(path, contents), Location::External => store.efs().write(path, contents), Location::Volatile => store.vfs().write(path, contents), - }.map_err(|_| Error::FilesystemWriteFailure) + } + .map_err(|_| Error::FilesystemWriteFailure) } /// Creates parent directory if necessary, then writes. #[inline(never)] -pub fn store(store: impl Store, location: Location, path: &Path, contents: &[u8]) -> Result<(), Error> { +pub fn store( + store: impl Store, + location: Location, + path: &Path, + contents: &[u8], +) -> Result<(), Error> { debug_now!("storing {}", &path); match location { Location::Internal => create_directories(store.ifs(), path)?, @@ -524,7 +573,11 @@ pub fn exists(store: impl Store, location: Location, path: &Path) -> bool { } #[inline(never)] -pub fn metadata(store: impl Store, location: Location, path: &Path) -> Result, Error> { +pub fn metadata( + store: impl Store, + location: Location, + path: &Path, +) -> Result, Error> { debug_now!("checking existence of {}", &path); let result = match location { Location::Internal => store.ifs().metadata(path), @@ -550,7 +603,12 @@ pub fn remove_dir(store: impl Store, location: Location, path: &Path) -> bool { } #[inline(never)] -pub fn remove_dir_all_where

(store: impl Store, location: Location, path: &Path, predicate: P) -> Result +pub fn remove_dir_all_where

( + store: impl Store, + location: Location, + path: &Path, + predicate: P, +) -> Result where P: Fn(&DirEntry) -> bool, { @@ -598,4 +656,3 @@ where // success // } - diff --git a/src/store/certstore.rs b/src/store/certstore.rs index 8f191374321..38637eaeeb5 100644 --- a/src/store/certstore.rs +++ b/src/store/certstore.rs @@ -26,29 +26,23 @@ pub trait Certstore { } impl Certstore for ClientCertstore { - fn delete_certificate(&mut self, id: CertId) -> Result<()> { let path = self.cert_path(id); - let locations = [ - Location::Internal, - Location::External, - Location::Volatile, - ]; - locations.iter().any(|&location| { - store::delete(self.store, location, &path) - }).then(|| ()).ok_or(Error::NoSuchKey) + let locations = [Location::Internal, Location::External, Location::Volatile]; + locations + .iter() + .any(|&location| store::delete(self.store, location, &path)) + .then(|| ()) + .ok_or(Error::NoSuchKey) } fn read_certificate(&mut self, id: CertId) -> Result { let path = self.cert_path(id); - let locations = [ - Location::Internal, - Location::External, - Location::Volatile, - ]; - locations.iter().find_map(|&location| { - store::read(self.store, location, &path).ok() - }).ok_or(Error::NoSuchCertificate) + let locations = [Location::Internal, Location::External, Location::Volatile]; + locations + .iter() + .find_map(|&location| store::read(self.store, location, &path).ok()) + .ok_or(Error::NoSuchCertificate) } fn write_certificate(&mut self, location: Location, der: &Message) -> Result { @@ -61,7 +55,11 @@ impl Certstore for ClientCertstore { impl ClientCertstore { pub fn new(client_id: ClientId, rng: ChaCha8Rng, store: S) -> Self { - Self { client_id, rng, store } + Self { + client_id, + rng, + store, + } } fn cert_path(&self, id: CertId) -> PathBuf { @@ -82,6 +80,4 @@ impl ClientCertstore { // let path = self.cert_path(id); // store::store(self.store, location, &path, &data) // } - } - diff --git a/src/store/counterstore.rs b/src/store/counterstore.rs index 2db12ecb244..4db24b623d8 100644 --- a/src/store/counterstore.rs +++ b/src/store/counterstore.rs @@ -1,14 +1,12 @@ - use chacha20::ChaCha8Rng; use littlefs2::path::PathBuf; use crate::{ error::{Error, Result}, store::{self, Store}, - types::{ClientId, CounterId, Location as Location}, + types::{ClientId, CounterId, Location}, }; - pub struct ClientCounterstore where S: Store, @@ -22,7 +20,11 @@ pub type Counter = u128; impl ClientCounterstore { pub fn new(client_id: ClientId, rng: ChaCha8Rng, store: S) -> Self { - Self { client_id, rng, store } + Self { + client_id, + rng, + store, + } } fn counter_path(&self, id: CounterId) -> PathBuf { @@ -56,7 +58,11 @@ impl ClientCounterstore { /// Trait intended for use by mechanism implementations. pub trait Counterstore { const DEFAULT_START_AT: u128 = 0; - fn create_starting_at(&mut self, location: Location, starting_at: impl Into) -> Result; + fn create_starting_at( + &mut self, + location: Location, + starting_at: impl Into, + ) -> Result; fn create(&mut self, location: Location) -> Result { self.create_starting_at(location, Self::DEFAULT_START_AT) } @@ -64,22 +70,23 @@ pub trait Counterstore { } impl Counterstore for ClientCounterstore { - fn create_starting_at(&mut self, location: Location, starting_at: impl Into) -> Result { + fn create_starting_at( + &mut self, + location: Location, + starting_at: impl Into, + ) -> Result { let id = CounterId::new(&mut self.rng); self.write_counter(location, id, starting_at.into())?; Ok(id) } fn increment(&mut self, id: CounterId) -> Result { - let locations = [ - Location::Internal, - Location::External, - Location::Volatile, - ]; + let locations = [Location::Internal, Location::External, Location::Volatile]; - locations.iter().filter_map(|&location| { - self.increment_location(location, id).ok() - }).next().ok_or(Error::NoSuchKey) + locations + .iter() + .filter_map(|&location| self.increment_location(location, id).ok()) + .next() + .ok_or(Error::NoSuchKey) } } - diff --git a/src/store/filestore.rs b/src/store/filestore.rs index f62777e1a3c..d0bc4899061 100644 --- a/src/store/filestore.rs +++ b/src/store/filestore.rs @@ -1,9 +1,9 @@ use crate::{ - Bytes, error::{Error, Result}, // service::ReadDirState, store::{self, Store}, - types::{Message, Location as Location, UserAttribute}, + types::{Location, Message, UserAttribute}, + Bytes, }; #[derive(Clone)] @@ -20,7 +20,10 @@ pub struct ReadDirFilesState { user_attribute: Option, } -use littlefs2::{fs::{DirEntry, Metadata}, path::{Path, PathBuf}}; +use littlefs2::{ + fs::{DirEntry, Metadata}, + path::{Path, PathBuf}, +}; pub type ClientId = PathBuf; pub struct ClientFilestore @@ -53,7 +56,9 @@ impl ClientFilestore { let offset = if absolute { 1 } else { 0 }; // we know `client_id` here, could use its length - let end_of_namespace = bytes[1..].iter().position(|&x| x == b'/') + let end_of_namespace = bytes[1..] + .iter() + .position(|&x| x == b'/') // oh oh oh .unwrap(); let dat_offset = "/dat/".len(); @@ -69,7 +74,12 @@ pub trait Filestore { fn remove_file(&mut self, path: &PathBuf, location: Location) -> Result<()>; fn remove_dir(&mut self, path: &PathBuf, location: Location) -> Result<()>; fn remove_dir_all(&mut self, path: &PathBuf, location: Location) -> Result; - fn locate_file(&mut self, location: Location, underneath: Option, filename: PathBuf) -> Result>; + fn locate_file( + &mut self, + location: Location, + underneath: Option, + filename: PathBuf, + ) -> Result>; /// Iterate over entries of a directory (both file and directory entries). /// @@ -80,15 +90,18 @@ pub trait Filestore { /// /// In case an entry was found, the returned option also contains state, so the expected /// call to `read_dir_next` can resume operation. - fn read_dir_first(&mut self, dir: &PathBuf, location: Location, not_before: Option<&PathBuf>) - -> Result>; + fn read_dir_first( + &mut self, + dir: &PathBuf, + location: Location, + not_before: Option<&PathBuf>, + ) -> Result>; /// Continue iterating over entries of a directory. /// /// Return the entry just after the previous one. If it exists, also return state for the /// following call. - fn read_dir_next(&mut self, state: ReadDirState) - -> Result>; + fn read_dir_next(&mut self, state: ReadDirState) -> Result>; /// Iterate over contents of files inside a directory. /// @@ -97,12 +110,18 @@ pub trait Filestore { /// with some sort of "fetch data"). /// /// Additionally, files may optionally be filtered via attributes. - fn read_dir_files_first(&mut self, clients_dir: &PathBuf, location: Location, user_attribute: Option) - -> Result, ReadDirFilesState)>>; + fn read_dir_files_first( + &mut self, + clients_dir: &PathBuf, + location: Location, + user_attribute: Option, + ) -> Result, ReadDirFilesState)>>; /// Continuation of `read_dir_files_first`. - fn read_dir_files_next(&mut self, state: ReadDirFilesState) - -> Result, ReadDirFilesState)>>; + fn read_dir_files_next( + &mut self, + state: ReadDirFilesState, + ) -> Result, ReadDirFilesState)>>; } impl Filestore for ClientFilestore { @@ -151,7 +170,12 @@ impl Filestore for ClientFilestore { .map_err(|_| Error::InternalError) } - fn read_dir_first(&mut self, clients_dir: &PathBuf, location: Location, not_before: Option<&PathBuf>) -> Result> { + fn read_dir_first( + &mut self, + clients_dir: &PathBuf, + location: Location, + not_before: Option<&PathBuf>, + ) -> Result> { if location != Location::Internal { return Err(Error::RequestNotAvailable); } @@ -159,74 +183,80 @@ impl Filestore for ClientFilestore { let dir = self.actual_path(clients_dir); - Ok(fs.read_dir_and_then(&dir, |it| { - - // this is an iterator with Item = (usize, Result) - it.enumerate() - - // skip over `.` and `..` - .skip(2) - - // todo: try ?-ing out of this (the API matches std::fs, where read/write errors - // can occur during operation) - // - // Option> -> ?? - .map(|(i, entry)| (i, entry.unwrap())) - - // if there is a "not_before" entry, skip all entries before it. - .find(|(_, entry)| { - if let Some(not_before) = not_before { - entry.file_name() == not_before.as_ref() - } else { true } - }) - - // if there is an entry, construct the state that needs storing out of it, - // remove the prefix from the entry's path to not leak implementation details to - // the client, and return both the entry and the state - .map(|(i, mut entry)| { - let read_dir_state = ReadDirState { real_dir: dir.clone(), last: i }; - let entry_client_path = self.client_path(entry.path()); - // trace_now!("converted path {} to client path {}", &entry.path(), &entry_client_path); - // This is a hidden function which allows us to modify `entry.path`. - // In regular use, `DirEntry` is not supposed to be constructable by the user - // (only by querying the filesystem), which is why the function is both - // hidden and tagged "unsafe" to discourage use. Our use case here is precisely - // the reason for its existence :) - *unsafe { entry.path_buf_mut() } = entry_client_path; - (entry, read_dir_state) - - // the `ok_or` dummy error followed by the `ok` in the next line is because - // `read_dir_and_then` wants to see Results (although we naturally have an Option - // at this point) - }).ok_or(littlefs2::io::Error::Io) - }).ok()) + Ok(fs + .read_dir_and_then(&dir, |it| { + // this is an iterator with Item = (usize, Result) + it.enumerate() + // skip over `.` and `..` + .skip(2) + // todo: try ?-ing out of this (the API matches std::fs, where read/write errors + // can occur during operation) + // + // Option> -> ?? + .map(|(i, entry)| (i, entry.unwrap())) + // if there is a "not_before" entry, skip all entries before it. + .find(|(_, entry)| { + if let Some(not_before) = not_before { + entry.file_name() == not_before.as_ref() + } else { + true + } + }) + // if there is an entry, construct the state that needs storing out of it, + // remove the prefix from the entry's path to not leak implementation details to + // the client, and return both the entry and the state + .map(|(i, mut entry)| { + let read_dir_state = ReadDirState { + real_dir: dir.clone(), + last: i, + }; + let entry_client_path = self.client_path(entry.path()); + // trace_now!("converted path {} to client path {}", &entry.path(), &entry_client_path); + // This is a hidden function which allows us to modify `entry.path`. + // In regular use, `DirEntry` is not supposed to be constructable by the user + // (only by querying the filesystem), which is why the function is both + // hidden and tagged "unsafe" to discourage use. Our use case here is precisely + // the reason for its existence :) + *unsafe { entry.path_buf_mut() } = entry_client_path; + (entry, read_dir_state) + + // the `ok_or` dummy error followed by the `ok` in the next line is because + // `read_dir_and_then` wants to see Results (although we naturally have an Option + // at this point) + }) + .ok_or(littlefs2::io::Error::Io) + }) + .ok()) } fn read_dir_next(&mut self, state: ReadDirState) -> Result> { - let ReadDirState { real_dir, last } = state; let fs = self.store.ifs(); // all we want to do here is skip just past the previously found entry // in the directory iterator, then return it (plus state to continue on next call) - Ok(fs.read_dir_and_then(&real_dir, |it| { - - // skip over previous - it.enumerate().nth(last + 1) - // entry is still a Result :/ (see question in `read_dir_first`) - .map(|(i,entry)| (i, entry.unwrap())) - // convert Option into Result, again because `read_dir_and_then` expects this - .map(|(i, mut entry)| { - let read_dir_state = ReadDirState { real_dir: real_dir.clone(), last: i }; - - let entry_client_path = self.client_path(entry.path()); - *unsafe { entry.path_buf_mut() } = entry_client_path; - - (entry, read_dir_state) - }) - .ok_or(littlefs2::io::Error::Io) - - }).ok()) + Ok(fs + .read_dir_and_then(&real_dir, |it| { + // skip over previous + it.enumerate() + .nth(last + 1) + // entry is still a Result :/ (see question in `read_dir_first`) + .map(|(i, entry)| (i, entry.unwrap())) + // convert Option into Result, again because `read_dir_and_then` expects this + .map(|(i, mut entry)| { + let read_dir_state = ReadDirState { + real_dir: real_dir.clone(), + last: i, + }; + + let entry_client_path = self.client_path(entry.path()); + *unsafe { entry.path_buf_mut() } = entry_client_path; + + (entry, read_dir_state) + }) + .ok_or(littlefs2::io::Error::Io) + }) + .ok()) } fn read_dir_files_first( @@ -235,7 +265,6 @@ impl Filestore for ClientFilestore { location: Location, user_attribute: Option, ) -> Result, ReadDirFilesState)>> { - if location != Location::Internal { return Err(Error::RequestNotAvailable); } @@ -243,96 +272,121 @@ impl Filestore for ClientFilestore { let dir = self.actual_path(clients_dir); - Ok(fs.read_dir_and_then(&dir, |it| { - - // this is an iterator with Item = (usize, Result) - it.enumerate() - - // todo: try ?-ing out of this (the API matches std::fs, where read/write errors - // can occur during operation) - // - // Option> -> ?? - .map(|(i, entry)| (i, entry.unwrap())) - - // skip over directories (including `.` and `..`) - .filter(|(_, entry)| entry.file_type().is_file()) - - // take first entry that meets requirements - .find(|(_, entry)| { - if let Some(user_attribute) = user_attribute.as_ref() { - let mut path = dir.clone(); - path.push(entry.file_name()); - let attribute = fs.attribute(&path, crate::config::USER_ATTRIBUTE_NUMBER).unwrap(); - - if let Some(attribute) = attribute { - user_attribute == attribute.data() + Ok(fs + .read_dir_and_then(&dir, |it| { + // this is an iterator with Item = (usize, Result) + it.enumerate() + // todo: try ?-ing out of this (the API matches std::fs, where read/write errors + // can occur during operation) + // + // Option> -> ?? + .map(|(i, entry)| (i, entry.unwrap())) + // skip over directories (including `.` and `..`) + .filter(|(_, entry)| entry.file_type().is_file()) + // take first entry that meets requirements + .find(|(_, entry)| { + if let Some(user_attribute) = user_attribute.as_ref() { + let mut path = dir.clone(); + path.push(entry.file_name()); + let attribute = fs + .attribute(&path, crate::config::USER_ATTRIBUTE_NUMBER) + .unwrap(); + + if let Some(attribute) = attribute { + user_attribute == attribute.data() + } else { + false + } } else { - false + true } - } else { true } - }) - - // if there is an entry, construct the state that needs storing out of it, - // and return the file's contents. - // the client, and return both the entry and the state - .map(|(i, entry)| { - let read_dir_files_state = ReadDirFilesState { real_dir: dir.clone(), last: i, location, user_attribute }; - // The semantics is that for a non-existent file, we return None (not an error) - let data = store::read(self.store, location, entry.path()).ok(); - (data, read_dir_files_state) - - // the `ok_or` dummy error followed by the `ok` in the next line is because - // `read_dir_and_then` wants to see Results (although we naturally have an Option - // at this point) - }).ok_or(littlefs2::io::Error::Io) - }).ok()) + }) + // if there is an entry, construct the state that needs storing out of it, + // and return the file's contents. + // the client, and return both the entry and the state + .map(|(i, entry)| { + let read_dir_files_state = ReadDirFilesState { + real_dir: dir.clone(), + last: i, + location, + user_attribute, + }; + // The semantics is that for a non-existent file, we return None (not an error) + let data = store::read(self.store, location, entry.path()).ok(); + (data, read_dir_files_state) + + // the `ok_or` dummy error followed by the `ok` in the next line is because + // `read_dir_and_then` wants to see Results (although we naturally have an Option + // at this point) + }) + .ok_or(littlefs2::io::Error::Io) + }) + .ok()) } - fn read_dir_files_next(&mut self, state: ReadDirFilesState) - -> Result, ReadDirFilesState)>> - { - let ReadDirFilesState { real_dir, last, location, user_attribute } = state; + fn read_dir_files_next( + &mut self, + state: ReadDirFilesState, + ) -> Result, ReadDirFilesState)>> { + let ReadDirFilesState { + real_dir, + last, + location, + user_attribute, + } = state; let fs = self.store.ifs(); // all we want to do here is skip just past the previously found entry // in the directory iterator, then return it (plus state to continue on next call) - Ok(fs.read_dir_and_then(&real_dir, |it| { - - // skip over previous - it.enumerate().skip(last + 1) - // entry is still a Result :/ (see question in `read_dir_first`) - .map(|(i,entry)| (i, entry.unwrap())) - - // skip over directories (including `.` and `..`) - .filter(|(_, entry)| entry.file_type().is_file()) - - // take first entry that meets requirements - .find(|(_, entry)| { - if let Some(user_attribute) = user_attribute.as_ref() { - let mut path = real_dir.clone(); - path.push(entry.file_name()); - let attribute = fs.attribute(&path, crate::config::USER_ATTRIBUTE_NUMBER).unwrap(); - if let Some(attribute) = attribute { - user_attribute == attribute.data() + Ok(fs + .read_dir_and_then(&real_dir, |it| { + // skip over previous + it.enumerate() + .skip(last + 1) + // entry is still a Result :/ (see question in `read_dir_first`) + .map(|(i, entry)| (i, entry.unwrap())) + // skip over directories (including `.` and `..`) + .filter(|(_, entry)| entry.file_type().is_file()) + // take first entry that meets requirements + .find(|(_, entry)| { + if let Some(user_attribute) = user_attribute.as_ref() { + let mut path = real_dir.clone(); + path.push(entry.file_name()); + let attribute = fs + .attribute(&path, crate::config::USER_ATTRIBUTE_NUMBER) + .unwrap(); + if let Some(attribute) = attribute { + user_attribute == attribute.data() + } else { + false + } } else { - false + true } - } else { true } - }) - - .map(|(i, entry)| { - let read_dir_files_state = ReadDirFilesState { real_dir: real_dir.clone(), last: i, location, user_attribute }; - // The semantics is that for a non-existent file, we return None (not an error) - let data = store::read(self.store, location, entry.path()).ok(); - (data, read_dir_files_state) - }) - - // convert Option into Result, again because `read_dir_and_then` expects this - .ok_or(littlefs2::io::Error::Io) - }).ok()) + }) + .map(|(i, entry)| { + let read_dir_files_state = ReadDirFilesState { + real_dir: real_dir.clone(), + last: i, + location, + user_attribute, + }; + // The semantics is that for a non-existent file, we return None (not an error) + let data = store::read(self.store, location, entry.path()).ok(); + (data, read_dir_files_state) + }) + // convert Option into Result, again because `read_dir_and_then` expects this + .ok_or(littlefs2::io::Error::Io) + }) + .ok()) } - fn locate_file(&mut self, location: Location, underneath: Option, filename: PathBuf) -> Result> { + fn locate_file( + &mut self, + location: Location, + underneath: Option, + filename: PathBuf, + ) -> Result> { if location != Location::Internal { return Err(Error::RequestNotAvailable); } @@ -346,14 +400,10 @@ impl Filestore for ClientFilestore { fn recursively_locate( fs: &'static crate::store::Fs, dir: PathBuf, - filename: &Path - ) - -> Option - { + filename: &Path, + ) -> Option { fs.read_dir_and_then(&dir, |it| { - - it - .map(|entry| entry.unwrap()) + it.map(|entry| entry.unwrap()) .skip(2) .filter_map(|entry| { let is_file = entry.file_type().is_file(); @@ -369,11 +419,11 @@ impl Filestore for ClientFilestore { }) .next() .ok_or(littlefs2::io::Error::Io) - }).ok() + }) + .ok() } - let path = recursively_locate(fs, dir, &filename) - .map(|path| self.client_path(&path)); + let path = recursively_locate(fs, dir, &filename).map(|path| self.client_path(&path)); Ok(path) } diff --git a/src/store/keystore.rs b/src/store/keystore.rs index abec9a88423..0346b225c7b 100644 --- a/src/store/keystore.rs +++ b/src/store/keystore.rs @@ -2,15 +2,13 @@ use chacha20::ChaCha8Rng; use littlefs2::path::PathBuf; use crate::{ - Bytes, error::{Error, Result}, key, - Platform, store::{self, Store as _}, types::{KeyId, Location}, + Bytes, Platform, }; - pub type ClientId = littlefs2::path::PathBuf; pub struct ClientKeystore

@@ -24,7 +22,11 @@ where impl ClientKeystore

{ pub fn new(client_id: ClientId, rng: ChaCha8Rng, store: P::S) -> Self { - Self { client_id, rng, store } + Self { + client_id, + rng, + store, + } } } @@ -35,20 +37,37 @@ pub trait Keystore { // fn store(&self, key: Key, location: Location) -> Result; // fn load(&self, key: KeyId) -> Result; // fn exists(&self, key: KeyId) -> bool; - fn store_key(&mut self, location: Location, secrecy: key::Secrecy, info: impl Into, material: &[u8]) -> Result; + fn store_key( + &mut self, + location: Location, + secrecy: key::Secrecy, + info: impl Into, + material: &[u8], + ) -> Result; fn exists_key(&self, secrecy: key::Secrecy, kind: Option, id: &KeyId) -> bool; /// Return Header of key, if it exists fn key_info(&self, secrecy: key::Secrecy, id: &KeyId) -> Option; fn delete_key(&self, id: &KeyId) -> bool; fn delete_all(&self, location: Location) -> Result; - fn load_key(&self, secrecy: key::Secrecy, kind: Option, id: &KeyId) -> Result; - fn overwrite_key(&self, location: Location, secrecy: key::Secrecy, kind: key::Kind, id: &KeyId, material: &[u8]) -> Result<()>; + fn load_key( + &self, + secrecy: key::Secrecy, + kind: Option, + id: &KeyId, + ) -> Result; + fn overwrite_key( + &self, + location: Location, + secrecy: key::Secrecy, + kind: key::Kind, + id: &KeyId, + material: &[u8], + ) -> Result<()>; fn rng(&mut self) -> &mut ChaCha8Rng; fn location(&self, secrecy: key::Secrecy, id: &KeyId) -> Option; } impl ClientKeystore

{ - pub fn generate_key_id(&mut self) -> KeyId { KeyId::new(self.rng()) } @@ -68,17 +87,21 @@ impl ClientKeystore

{ path.push(&PathBuf::from(id.hex().as_slice())); path } - } impl Keystore for ClientKeystore

{ - fn rng(&mut self) -> &mut ChaCha8Rng { &mut self.rng } #[inline(never)] - fn store_key(&mut self, location: Location, secrecy: key::Secrecy, info: impl Into, material: &[u8]) -> Result { + fn store_key( + &mut self, + location: Location, + secrecy: key::Secrecy, + info: impl Into, + material: &[u8], + ) -> Result { // info_now!("storing {:?} -> {:?}", &key_kind, location); let mut info: key::Info = info.into(); @@ -103,27 +126,25 @@ impl Keystore for ClientKeystore

{ } fn key_info(&self, secrecy: key::Secrecy, id: &KeyId) -> Option { - self.load_key(secrecy, None, id).map(|key| key::Info { flags: key.flags, kind: key.kind }).ok() + self.load_key(secrecy, None, id) + .map(|key| key::Info { + flags: key.flags, + kind: key.kind, + }) + .ok() } // TODO: is this an Oracle? fn delete_key(&self, id: &KeyId) -> bool { - let secrecies = [ - key::Secrecy::Secret, - key::Secrecy::Public, - ]; + let secrecies = [key::Secrecy::Secret, key::Secrecy::Public]; - let locations = [ - Location::Internal, - Location::External, - Location::Volatile, - ]; + let locations = [Location::Internal, Location::External, Location::Volatile]; secrecies.iter().any(|secrecy| { let path = self.key_path(*secrecy, id); - locations.iter().any(|location| { - store::delete(self.store, *location, &path) - }) + locations + .iter() + .any(|location| store::delete(self.store, *location, &path)) }) } @@ -140,7 +161,12 @@ impl Keystore for ClientKeystore

{ }) } - fn load_key(&self, secrecy: key::Secrecy, kind: Option, id: &KeyId) -> Result { + fn load_key( + &self, + secrecy: key::Secrecy, + kind: Option, + id: &KeyId, + ) -> Result { // info_now!("loading {:?}", &key_kind); let path = self.key_path(secrecy, id); @@ -158,7 +184,14 @@ impl Keystore for ClientKeystore

{ Ok(key) } - fn overwrite_key(&self, location: Location, secrecy: key::Secrecy, kind: key::Kind, id: &KeyId, material: &[u8]) -> Result<()> { + fn overwrite_key( + &self, + location: Location, + secrecy: key::Secrecy, + kind: key::Kind, + id: &KeyId, + material: &[u8], + ) -> Result<()> { let mut flags = key::Flags::default(); if secrecy == key::Secrecy::Secret { flags |= key::Flags::SENSITIVE; @@ -175,7 +208,6 @@ impl Keystore for ClientKeystore

{ Ok(()) } - fn location(&self, secrecy: key::Secrecy, id: &KeyId) -> Option { let path = self.key_path(secrecy, id); @@ -193,5 +225,4 @@ impl Keystore for ClientKeystore

{ None } - } diff --git a/src/tests.rs b/src/tests.rs index 911580a76aa..a83d5921bda 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,17 +1,14 @@ #![cfg(test)] use chacha20::ChaCha20; -use crate::*; use crate::types::*; -use littlefs2::fs::{Allocation, Filesystem}; -use littlefs2::const_ram_storage; -use interchange::Interchange; +use crate::*; use entropy::shannon_entropy; +use interchange::Interchange; +use littlefs2::const_ram_storage; +use littlefs2::fs::{Allocation, Filesystem}; -use crate::client::{ - CryptoClient as _, - FilesystemClient as _, -}; +use crate::client::{CryptoClient as _, FilesystemClient as _}; pub struct MockRng(ChaCha20); @@ -45,27 +42,19 @@ impl crate::service::RngCore for MockRng { } } - - #[derive(Default)] -pub struct UserInterface { -} +pub struct UserInterface {} -impl crate::platform::UserInterface for UserInterface -{ +impl crate::platform::UserInterface for UserInterface { fn check_user_presence(&mut self) -> consent::Level { consent::Level::Normal } fn set_status(&mut self, status: ui::Status) { - println!("Set status: {:?}", status); - } - fn refresh(&mut self) { - - } + fn refresh(&mut self) {} fn uptime(&mut self) -> core::time::Duration { core::time::Duration::from_millis(1000) @@ -77,85 +66,85 @@ impl crate::platform::UserInterface for UserInterface } fn wink(&mut self, _duration: core::time::Duration) {} - } -const_ram_storage!(InternalStorage, 4096*10); -const_ram_storage!(ExternalStorage, 4096*10); -const_ram_storage!(VolatileStorage, 4096*10); - - - +const_ram_storage!(InternalStorage, 4096 * 10); +const_ram_storage!(ExternalStorage, 4096 * 10); +const_ram_storage!(VolatileStorage, 4096 * 10); // Using macro to avoid maintaining the type declarations macro_rules! create_memory { - () => { - { - - let filesystem = InternalStorage::new(); - static mut INTERNAL_STORAGE: Option = None; - unsafe { INTERNAL_STORAGE = Some(filesystem); } - static mut INTERNAL_FS_ALLOC: Option> = None; - unsafe { INTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - - static mut EXTERNAL_STORAGE: ExternalStorage = ExternalStorage::new(); - static mut EXTERNAL_FS_ALLOC: Option> = None; - unsafe { EXTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - - static mut VOLATILE_STORAGE: VolatileStorage = VolatileStorage::new(); - static mut VOLATILE_FS_ALLOC: Option> = None; - unsafe { VOLATILE_FS_ALLOC = Some(Filesystem::allocate()); } - - ( - unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, - unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, - unsafe { &mut EXTERNAL_STORAGE }, - unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, - unsafe { &mut VOLATILE_STORAGE }, - ) + () => {{ + let filesystem = InternalStorage::new(); + static mut INTERNAL_STORAGE: Option = None; + unsafe { + INTERNAL_STORAGE = Some(filesystem); + } + static mut INTERNAL_FS_ALLOC: Option> = None; + unsafe { + INTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - }; - // Create a "copy" - ($memory: expr) => { - { - let mem_2 = unsafe{&*(&$memory as *const ( - &'static mut littlefs2::fs::Allocation, - &'static mut InternalStorage, - &'static mut littlefs2::fs::Allocation, - &'static mut ExternalStorage, - &'static mut littlefs2::fs::Allocation, - &'static mut VolatileStorage, - ))}; - let mem_2 = ( - (mem_2.0 as *const littlefs2::fs::Allocation) as u64, - (mem_2.1 as *const InternalStorage) as u64, - (mem_2.2 as *const littlefs2::fs::Allocation) as u64, - (mem_2.3 as *const ExternalStorage) as u64, - (mem_2.4 as *const littlefs2::fs::Allocation) as u64, - (mem_2.5 as *const VolatileStorage) as u64, - ); - let mem_2: ( - &'static mut littlefs2::fs::Allocation, - &'static mut InternalStorage, - &'static mut littlefs2::fs::Allocation, - &'static mut ExternalStorage, - &'static mut littlefs2::fs::Allocation, - &'static mut VolatileStorage, - ) = ( - unsafe{std::mem::transmute(mem_2.0)}, - unsafe{std::mem::transmute(mem_2.1)}, - unsafe{std::mem::transmute(mem_2.2)}, - unsafe{std::mem::transmute(mem_2.3)}, - unsafe{std::mem::transmute(mem_2.4)}, - unsafe{std::mem::transmute(mem_2.5)}, - ); - - mem_2 + static mut EXTERNAL_STORAGE: ExternalStorage = ExternalStorage::new(); + static mut EXTERNAL_FS_ALLOC: Option> = None; + unsafe { + EXTERNAL_FS_ALLOC = Some(Filesystem::allocate()); } - } + static mut VOLATILE_STORAGE: VolatileStorage = VolatileStorage::new(); + static mut VOLATILE_FS_ALLOC: Option> = None; + unsafe { + VOLATILE_FS_ALLOC = Some(Filesystem::allocate()); + } + + ( + unsafe { INTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { INTERNAL_STORAGE.as_mut().unwrap() }, + unsafe { EXTERNAL_FS_ALLOC.as_mut().unwrap() }, + unsafe { &mut EXTERNAL_STORAGE }, + unsafe { VOLATILE_FS_ALLOC.as_mut().unwrap() }, + unsafe { &mut VOLATILE_STORAGE }, + ) + }}; + // Create a "copy" + ($memory: expr) => {{ + let mem_2 = unsafe { + &*(&$memory + as *const ( + &'static mut littlefs2::fs::Allocation, + &'static mut InternalStorage, + &'static mut littlefs2::fs::Allocation, + &'static mut ExternalStorage, + &'static mut littlefs2::fs::Allocation, + &'static mut VolatileStorage, + )) + }; + let mem_2 = ( + (mem_2.0 as *const littlefs2::fs::Allocation) as u64, + (mem_2.1 as *const InternalStorage) as u64, + (mem_2.2 as *const littlefs2::fs::Allocation) as u64, + (mem_2.3 as *const ExternalStorage) as u64, + (mem_2.4 as *const littlefs2::fs::Allocation) as u64, + (mem_2.5 as *const VolatileStorage) as u64, + ); + let mem_2: ( + &'static mut littlefs2::fs::Allocation, + &'static mut InternalStorage, + &'static mut littlefs2::fs::Allocation, + &'static mut ExternalStorage, + &'static mut littlefs2::fs::Allocation, + &'static mut VolatileStorage, + ) = ( + unsafe { std::mem::transmute(mem_2.0) }, + unsafe { std::mem::transmute(mem_2.1) }, + unsafe { std::mem::transmute(mem_2.2) }, + unsafe { std::mem::transmute(mem_2.3) }, + unsafe { std::mem::transmute(mem_2.4) }, + unsafe { std::mem::transmute(mem_2.5) }, + ); + + mem_2 + }}; } // TODO: what's going on here? Duplicates code in `tests/client/mod.rs`. @@ -166,64 +155,54 @@ macro_rules! setup { setup!($client, Store, Platform, memory, [0u8; 32], true); }; ($client:ident, $store:ident, $platform: ident, $memory:expr, $seed:expr, $reformat: expr) => { + store!( + $store, + Internal: InternalStorage, + External: ExternalStorage, + Volatile: VolatileStorage + ); + platform!($platform, R: MockRng, S: $store, UI: UserInterface,); + + let store = $store::claim().unwrap(); + + store + .mount( + $memory.0, $memory.1, $memory.2, $memory.3, $memory.4, $memory.5, $reformat, + ) + .unwrap(); + let rng = MockRng::new(); + let pc_interface: UserInterface = Default::default(); - store!($store, - Internal: InternalStorage, - External: ExternalStorage, - Volatile: VolatileStorage - ); - platform!($platform, - R: MockRng, - S: $store, - UI: UserInterface, - ); - - let store = $store::claim().unwrap(); - - store.mount( - $memory.0, - $memory.1, - $memory.2, - $memory.3, - $memory.4, - $memory.5, - $reformat, - ).unwrap(); - - - let rng = MockRng::new(); - let pc_interface: UserInterface = Default::default(); - - let platform = $platform::new(rng, store, pc_interface); - let mut trussed: crate::Service<$platform> = crate::service::Service::new(platform); + let platform = $platform::new(rng, store, pc_interface); + let mut trussed: crate::Service<$platform> = crate::service::Service::new(platform); - unsafe { crate::pipe::TrussedInterchange::reset_claims(); } - let (test_trussed_requester, test_trussed_responder) = crate::pipe::TrussedInterchange::claim() + unsafe { + crate::pipe::TrussedInterchange::reset_claims(); + } + let (test_trussed_requester, test_trussed_responder) = + crate::pipe::TrussedInterchange::claim() .expect("could not setup TEST TrussedInterchange"); - let test_client_id = "TEST".into(); - - assert!(trussed.add_endpoint(test_trussed_responder, test_client_id).is_ok()); - - trussed.set_seed_if_uninitialized(&$seed); - let mut $client = { - pub type TestClient<'a> = crate::ClientImplementation<&'a mut crate::Service<$platform>>; - TestClient::new( - test_trussed_requester, - &mut trussed - ) - }; - - } + let test_client_id = "TEST".into(); + + assert!(trussed + .add_endpoint(test_trussed_responder, test_client_id) + .is_ok()); + + trussed.set_seed_if_uninitialized(&$seed); + let mut $client = { + pub type TestClient<'a> = + crate::ClientImplementation<&'a mut crate::Service<$platform>>; + TestClient::new(test_trussed_requester, &mut trussed) + }; + }; } #[test] #[serial] fn dummy() { - setup!(_client); - - } +} #[test] #[serial] @@ -232,35 +211,48 @@ fn sign_ed255() { setup!(client); use crate::client::mechanisms::{Ed255, P256}; - let future = client.generate_ed255_private_key(Location::Internal).expect("no client error"); + let future = client + .generate_ed255_private_key(Location::Internal) + .expect("no client error"); println!("submitted gen ed255"); let reply = block!(future); let private_key = reply.expect("no errors, never").key; println!("got a private key {:?}", &private_key); - let public_key = block!(client.derive_ed255_public_key(private_key, Location::Volatile).expect("no client error")) - .expect("no issues").key; + let public_key = block!(client + .derive_ed255_public_key(private_key, Location::Volatile) + .expect("no client error")) + .expect("no issues") + .key; println!("got a public key {:?}", &public_key); - assert!(block!( - client.derive_ed255_public_key(private_key, Location::Volatile).expect("no client error wot") - ).is_ok()); - assert!(block!( - client.derive_p256_public_key(private_key, Location::Volatile).expect("no client error wot") - ).is_err()); + assert!(block!(client + .derive_ed255_public_key(private_key, Location::Volatile) + .expect("no client error wot")) + .is_ok()); + assert!(block!(client + .derive_p256_public_key(private_key, Location::Volatile) + .expect("no client error wot")) + .is_err()); let message = [1u8, 2u8, 3u8]; - let future = client.sign_ed255(private_key, &message).expect("no client error post err"); + let future = client + .sign_ed255(private_key, &message) + .expect("no client error post err"); let reply: Result = block!(future); let signature = reply.expect("good signature").signature; println!("got a signature: {:?}", &signature); - let future = client.verify_ed255(public_key, &message, &signature).expect("no client error"); + let future = client + .verify_ed255(public_key, &message, &signature) + .expect("no client error"); let reply = block!(future); let valid = reply.expect("good signature").valid; assert!(valid); - let future = client.verify_ed255(public_key, &message, &[1u8,2,3]).expect("no client error"); + let future = client + .verify_ed255(public_key, &message, &[1u8, 2, 3]) + .expect("no client error"); let reply = block!(future); assert_eq!(Err(Error::WrongSignatureLength), reply); } @@ -271,30 +263,37 @@ fn sign_p256() { use crate::client::mechanisms::P256 as _; // let mut client = setup!(); setup!(client); - let private_key = block!(client.generate_p256_private_key(Location::External).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &private_key); - let public_key = block!(client.derive_p256_public_key(private_key, Location::Volatile).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &public_key); - - let message = [1u8, 2u8, 3u8]; - let signature = block!(client.sign_p256(private_key, &message, SignatureSerialization::Raw) - .expect("no client error")) - .expect("good signature") - .signature; - - // use core::convert::AsMut; - // let sig = signature.0.as_mut()[0] = 0; - let future = client.verify_p256(public_key, &message, &signature); - let future = future.expect("no client error"); - let result = block!(future); - if result.is_err() { - println!("error: {:?}", result); - } - let reply = result.expect("valid signature"); - let valid = reply.valid; - assert!(valid); + let private_key = block!(client + .generate_p256_private_key(Location::External) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &private_key); + let public_key = block!(client + .derive_p256_public_key(private_key, Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &public_key); + + let message = [1u8, 2u8, 3u8]; + let signature = block!(client + .sign_p256(private_key, &message, SignatureSerialization::Raw) + .expect("no client error")) + .expect("good signature") + .signature; + + // use core::convert::AsMut; + // let sig = signature.0.as_mut()[0] = 0; + let future = client.verify_p256(public_key, &message, &signature); + let future = future.expect("no client error"); + let result = block!(future); + if result.is_err() { + println!("error: {:?}", result); + } + let reply = result.expect("valid signature"); + let valid = reply.valid; + assert!(valid); } #[test] @@ -303,47 +302,80 @@ fn agree_p256() { // let mut client = setup!(); use crate::client::mechanisms::P256; setup!(client); - let plat_private_key = block!(client.generate_p256_private_key(Location::Volatile).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &plat_private_key); - let plat_public_key = block!(client.derive_p256_public_key(plat_private_key, Location::Volatile).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &plat_public_key); - - let auth_private_key = block!(client.generate_p256_private_key(Location::Volatile).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &auth_private_key); - let auth_public_key = block!(client.derive_p256_public_key(auth_private_key, Location::Volatile).expect("no client error")) - .expect("no errors").key; - println!("got a public key {:?}", &auth_public_key); - - let shared_secret = block!( - client.agree(Mechanism::P256, auth_private_key.clone(), plat_public_key.clone(), - StorageAttributes::new().set_persistence(Location::Volatile)) - .expect("no client error")) - .expect("no errors").shared_secret; - - let alt_shared_secret = block!( - client.agree(Mechanism::P256, plat_private_key.clone(), auth_public_key.clone(), - StorageAttributes::new().set_persistence(Location::Volatile)) - .expect("no client error")) - .expect("no errors").shared_secret; - - // NB: we have no idea about the value of keys, these are just *different* handles - assert_ne!(&shared_secret, &alt_shared_secret); - - let symmetric_key = block!( - client.derive_key(Mechanism::Sha256, shared_secret.clone(), None, - StorageAttributes::new().set_persistence(Location::Volatile)) - .expect("no client error")) - .expect("no errors").key; - - let new_pin_enc = [1u8, 2, 3]; - - let _tag = block!( - client.sign(Mechanism::HmacSha256, symmetric_key.clone(), &new_pin_enc, SignatureSerialization::Raw) - .expect("no client error")) - .expect("no errors").signature; + let plat_private_key = block!(client + .generate_p256_private_key(Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &plat_private_key); + let plat_public_key = block!(client + .derive_p256_public_key(plat_private_key, Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &plat_public_key); + + let auth_private_key = block!(client + .generate_p256_private_key(Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &auth_private_key); + let auth_public_key = block!(client + .derive_p256_public_key(auth_private_key, Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; + println!("got a public key {:?}", &auth_public_key); + + let shared_secret = block!(client + .agree( + Mechanism::P256, + auth_private_key.clone(), + plat_public_key.clone(), + StorageAttributes::new().set_persistence(Location::Volatile) + ) + .expect("no client error")) + .expect("no errors") + .shared_secret; + + let alt_shared_secret = block!(client + .agree( + Mechanism::P256, + plat_private_key.clone(), + auth_public_key.clone(), + StorageAttributes::new().set_persistence(Location::Volatile) + ) + .expect("no client error")) + .expect("no errors") + .shared_secret; + + // NB: we have no idea about the value of keys, these are just *different* handles + assert_ne!(&shared_secret, &alt_shared_secret); + + let symmetric_key = block!(client + .derive_key( + Mechanism::Sha256, + shared_secret.clone(), + None, + StorageAttributes::new().set_persistence(Location::Volatile) + ) + .expect("no client error")) + .expect("no errors") + .key; + + let new_pin_enc = [1u8, 2, 3]; + + let _tag = block!(client + .sign( + Mechanism::HmacSha256, + symmetric_key.clone(), + &new_pin_enc, + SignatureSerialization::Raw + ) + .expect("no client error")) + .expect("no errors") + .signature; } #[test] @@ -351,32 +383,32 @@ fn agree_p256() { fn aead() { use crate::client::mechanisms::Chacha8Poly1305; setup!(client); - let secret_key = - block!( - client - .generate_chacha8poly1305_key(Location::Volatile) - .expect("no client error") - ) - .expect("no errors") - .key; + let secret_key = block!(client + .generate_chacha8poly1305_key(Location::Volatile) + .expect("no client error")) + .expect("no errors") + .key; println!("got a key {:?}", &secret_key); let message = b"test message"; let associated_data = b"solokeys.com"; - let api::reply::Encrypt { ciphertext, nonce, tag } = - block!(client.encrypt_chacha8poly1305(secret_key, message, associated_data, None).expect("no client error")) - .expect("no errors"); - - let plaintext = - block!(client.decrypt_chacha8poly1305( - secret_key, - &ciphertext, - associated_data, - &nonce, - &tag, - ).map_err(drop).expect("no client error")) - .map_err(drop).expect("no errors").plaintext; + let api::reply::Encrypt { + ciphertext, + nonce, + tag, + } = block!(client + .encrypt_chacha8poly1305(secret_key, message, associated_data, None) + .expect("no client error")) + .expect("no errors"); + + let plaintext = block!(client + .decrypt_chacha8poly1305(secret_key, &ciphertext, associated_data, &nonce, &tag,) + .map_err(drop) + .expect("no client error")) + .map_err(drop) + .expect("no errors") + .plaintext; assert_eq!(&message[..], plaintext.unwrap().as_ref()); } @@ -384,30 +416,22 @@ fn aead() { #[test] #[serial] fn rng() { - macro_rules! gen_bytes { - ($client:expr, $size: expr) => { - { - assert!(($size % 128) == 0); - let mut rng_bytes = [0u8; $size]; - for x in (0..$size).step_by(128) { - let rng_chunk = - block!( - $client - .random_bytes(128) - .expect("no client error") - ) - .expect("no errors") - .bytes; - rng_bytes[x .. x + 128].clone_from_slice(&rng_chunk); - } - rng_bytes + ($client:expr, $size: expr) => {{ + assert!(($size % 128) == 0); + let mut rng_bytes = [0u8; $size]; + for x in (0..$size).step_by(128) { + let rng_chunk = block!($client.random_bytes(128).expect("no client error")) + .expect("no errors") + .bytes; + rng_bytes[x..x + 128].clone_from_slice(&rng_chunk); } - } + rng_bytes + }}; } setup!(client1); - let bytes = gen_bytes!(client1, 1024*100); + let bytes = gen_bytes!(client1, 1024 * 100); let entropy = shannon_entropy(&bytes); println!("got entropy of {} bytes: {}", bytes.len(), entropy); assert!(entropy > 7.99); @@ -417,17 +441,38 @@ fn rng() { let mem1 = create_memory!(); let mem2 = create_memory!(); let mem3 = create_memory!(); - setup!(client_twin1, StoreTwin1, PlatformTwin1, mem1, [0x01u8; 32], true); - setup!(client_twin2, StoreTwin2, PlatformTwin2, mem2, [0x01u8; 32], true); - setup!(client_3, StoreTwin3, PlatformTwin3, mem3, [0x02u8; 32], true); - let bytes_twin1 = gen_bytes!(client_twin1, 1024*100); - let bytes_twin2 = gen_bytes!(client_twin2, 1024*100); - let bytes_3 = gen_bytes!(client_3, 1024*100); - - for i in 0 .. bytes_twin2.len() { + setup!( + client_twin1, + StoreTwin1, + PlatformTwin1, + mem1, + [0x01u8; 32], + true + ); + setup!( + client_twin2, + StoreTwin2, + PlatformTwin2, + mem2, + [0x01u8; 32], + true + ); + setup!( + client_3, + StoreTwin3, + PlatformTwin3, + mem3, + [0x02u8; 32], + true + ); + let bytes_twin1 = gen_bytes!(client_twin1, 1024 * 100); + let bytes_twin2 = gen_bytes!(client_twin2, 1024 * 100); + let bytes_3 = gen_bytes!(client_3, 1024 * 100); + + for i in 0..bytes_twin2.len() { assert!(bytes_twin1[i] == bytes_twin2[i]); } - for i in 0 .. bytes_twin2.len() { + for i in 0..bytes_twin2.len() { // bytes_3 was from different seed. if bytes_3[i] != bytes_twin2[i] { break; @@ -441,24 +486,37 @@ fn rng() { let mem_copy = create_memory!(mem); // Trussed saves the RNG state so it cannot produce the same RNG on different boots. - setup!(client_twin3, StoreTwin4, PlatformTwin4, mem, [0x01u8; 32], true); + setup!( + client_twin3, + StoreTwin4, + PlatformTwin4, + mem, + [0x01u8; 32], + true + ); let first_128 = gen_bytes!(client_twin3, 128); // This time don't reformat the memory -- should pick up on last rng state. - setup!(client_twin4, StoreTwin5, PlatformTwin5, mem_copy, [0x01u8; 32], false); + setup!( + client_twin4, + StoreTwin5, + PlatformTwin5, + mem_copy, + [0x01u8; 32], + false + ); let second_128 = gen_bytes!(client_twin4, 128); let mut mismatch_count = 0; - for i in 0 .. 128 { + for i in 0..128 { assert!(first_128[i] == bytes_twin2[i]); if first_128[i] != second_128[i] { mismatch_count += 1; } } assert!(mismatch_count > 100); - } #[test] @@ -466,80 +524,60 @@ fn rng() { fn filesystem() { setup!(client); - assert!( - block!( - client - .entry_metadata(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) - .expect("no errors") - .metadata - .is_none(), - ); + assert!(block!(client + .entry_metadata(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) + .expect("no errors") + .metadata + .is_none(),); let data = Bytes::from_slice(&[0; 20]).unwrap(); - block!( - client - .write_file( - Location::Internal, - PathBuf::from("test_file"), - data.clone(), - None, - ) - .expect("no client error") - ) + block!(client + .write_file( + Location::Internal, + PathBuf::from("test_file"), + data.clone(), + None, + ) + .expect("no client error")) .expect("no errors"); - let recv_data = block!( - client - .read_file(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) + let recv_data = block!(client + .read_file(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) .expect("no errors") .data; assert_eq!(data, recv_data); - let metadata = block!( - client - .entry_metadata(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) + let metadata = block!(client + .entry_metadata(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) .expect("no errors") .metadata .unwrap(); assert!(metadata.is_file()); // This returns an error because the name doesn't exist - block!( - client - .remove_file(Location::Internal, PathBuf::from("bad_name")) - .expect("no client error") - ) + block!(client + .remove_file(Location::Internal, PathBuf::from("bad_name")) + .expect("no client error")) .ok(); - let metadata = block!( - client - .entry_metadata(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) + let metadata = block!(client + .entry_metadata(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) .expect("no errors") .metadata .unwrap(); assert!(metadata.is_file()); - block!( - client - .remove_file(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) + block!(client + .remove_file(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) .expect("no errors"); - assert!( - block!( - client - .entry_metadata(Location::Internal, PathBuf::from("test_file")) - .expect("no client error") - ) - .expect("no errors") - .metadata - .is_none(), - ); + assert!(block!(client + .entry_metadata(Location::Internal, PathBuf::from("test_file")) + .expect("no client error")) + .expect("no errors") + .metadata + .is_none(),); } diff --git a/src/types.rs b/src/types.rs index 965a048d90e..9194354612d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,16 +3,13 @@ use core::ops::Deref; pub use generic_array::GenericArray; -pub use heapless::{ - String, - Vec, -}; +pub use heapless::{String, Vec}; pub use crate::Bytes; pub use littlefs2::{ - fs::{DirEntry, Metadata, Filesystem}, driver::Storage as LfsStorage, + fs::{DirEntry, Filesystem, Metadata}, io::Result as LfsResult, path::PathBuf, }; @@ -23,8 +20,8 @@ use serde::{Deserialize, Serialize}; use crate::config::*; use crate::key::Secrecy; -pub use crate::platform::Platform; pub use crate::client::FutureResult; +pub use crate::platform::Platform; /// The ID of a Trussed object. /// @@ -51,7 +48,6 @@ impl core::fmt::Debug for Id { } } - pub type SpecialId = u8; pub trait ObjectId: Deref {} @@ -75,7 +71,7 @@ impl Id { let mut buffer = Bytes::new(); let array = self.0.to_be_bytes(); - for i in 0 .. array.len() { + for i in 0..array.len() { if array[i] == 0 && i != (array.len() - 1) { // Skip leading zeros. continue; @@ -117,39 +113,42 @@ impl Id { // } } -macro_rules! impl_id { ($Name:ident) => { - #[derive(Copy, Clone, Debug, serde::Deserialize, PartialEq, PartialOrd, serde::Serialize)] - #[serde(transparent)] - pub struct $Name(pub(crate) Id); - impl Eq for $Name {} - - impl ObjectId for $Name {} - - /// TODO: Is this a good idea (motivation: save implementions...) - impl Deref for $Name { - type Target = Id; - fn deref(&self) -> &Self::Target { - &self.0 +macro_rules! impl_id { + ($Name:ident) => { + #[derive( + Copy, Clone, Debug, serde::Deserialize, PartialEq, PartialOrd, serde::Serialize, + )] + #[serde(transparent)] + pub struct $Name(pub(crate) Id); + impl Eq for $Name {} + + impl ObjectId for $Name {} + + /// TODO: Is this a good idea (motivation: save implementions...) + impl Deref for $Name { + type Target = Id; + fn deref(&self) -> &Self::Target { + &self.0 + } } - } - impl $Name { - pub fn new(rng: &mut (impl CryptoRng + RngCore)) -> Self { - Self(Id::new(rng)) - } + impl $Name { + pub fn new(rng: &mut (impl CryptoRng + RngCore)) -> Self { + Self(Id::new(rng)) + } - pub const fn from_special(special_id: u8) -> Self { - Self(Id(special_id as _)) + pub const fn from_special(special_id: u8) -> Self { + Self(Id(special_id as _)) + } } - } - impl From for $Name { - fn from(id: u8) -> Self { - Self(Id(id as _)) + impl From for $Name { + fn from(id: u8) -> Self { + Self(Id(id as _)) + } } - } - -}} + }; +} impl_id!(CertId); impl_id!(CounterId); @@ -160,7 +159,6 @@ impl_id!(KeyId); // impl_id!(PublicKeyId); // impl_id!(SecretKeyId); - pub mod ui { use super::*; @@ -247,7 +245,6 @@ pub type ClientId = PathBuf; // - Mechanism // - Profiles - #[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] #[allow(clippy::large_enum_variant)] pub enum Attributes { @@ -278,7 +275,6 @@ pub enum CertificateType { // pub certificate_type CertificateType, // } - #[derive(Clone, Default, Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct DataAttributes { // application that manages the object @@ -370,8 +366,7 @@ impl<'de> serde::Deserialize<'de> for Id { { struct ValueVisitor<'de>(PhantomData<&'de ()>); - impl<'de> serde::de::Visitor<'de> for ValueVisitor<'de> - { + impl<'de> serde::de::Visitor<'de> for ValueVisitor<'de> { type Value = Id; fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -393,7 +388,6 @@ impl<'de> serde::Deserialize<'de> for Id { } } - #[derive(Clone, Eq, PartialEq, Debug)] pub enum ObjectType { Certificate(CertificateType), @@ -450,14 +444,12 @@ pub struct StorageAttributes { // // cryptoki: token (vs session) object // persistent: bool, pub persistence: Location, - // cryptoki: user must be logged in // private: bool, // modifiable: bool, // copyable: bool, // destroyable: bool, - } impl StorageAttributes { @@ -474,9 +466,7 @@ impl StorageAttributes { // unique_id, // label: String::new(), // persistent: false, - persistence: Location::Volatile, - // modifiable: true, // copyable: true, // destroyable: true, @@ -537,4 +527,3 @@ pub enum SignatureSerialization { } pub type UserAttribute = Bytes; - diff --git a/src/virt.rs b/src/virt.rs index 3b493f37bdf..2c8ba4eb37c 100644 --- a/src/virt.rs +++ b/src/virt.rs @@ -1,5 +1,5 @@ -mod ui; mod store; +mod ui; use std::{path::PathBuf, sync::Mutex}; @@ -10,16 +10,15 @@ use rand_core::SeedableRng as _; use crate::{ client::mechanisms::{Ed255 as _, P256 as _}, pipe::TrussedInterchange, - service::Service, - types::Location, - ClientImplementation, - Interchange as _, platform, + service::Service, syscall, + types::Location, + ClientImplementation, Interchange as _, }; -pub use ui::UserInterface; pub use store::{Filesystem, Ram, StoreProvider}; +pub use ui::UserInterface; pub type Client = ClientImplementation>>; @@ -28,9 +27,7 @@ const CLIENT_ID_ATTN: &str = "attn"; // We need this mutex to make sure that: // - TrussedInterchange is not used concurrently // - the Store is not used concurrently -static MUTEX: Lazy> = Lazy::new(|| { - Mutex::new(()) -}); +static MUTEX: Lazy> = Lazy::new(|| Mutex::new(())); pub fn with_platform(store: S, f: F) -> R where @@ -81,7 +78,7 @@ impl Platform { pub fn run_client( self, client_id: &str, - test: impl FnOnce(ClientImplementation>) -> R + test: impl FnOnce(ClientImplementation>) -> R, ) -> R { let service = Service::from(self); let client = service.try_into_new_client(client_id).unwrap(); @@ -92,8 +89,12 @@ impl Platform { impl From> for Service> { fn from(platform: Platform) -> Self { // reset platform - unsafe { TrussedInterchange::reset_claims(); } - unsafe { platform.store.reset(); } + unsafe { + TrussedInterchange::reset_claims(); + } + unsafe { + platform.store.reset(); + } let mut service = Service::new(platform); @@ -103,8 +104,10 @@ impl From> for Service> { syscall!(attn_client.generate_p256_private_key(Location::Internal)); // destroy this attestation client - unsafe { TrussedInterchange::reset_claims(); } - + unsafe { + TrussedInterchange::reset_claims(); + } + service } } diff --git a/src/virt/store.rs b/src/virt/store.rs index 03f151b3eec..19de6f49292 100644 --- a/src/virt/store.rs +++ b/src/virt/store.rs @@ -1,6 +1,6 @@ use std::{ - io::{Read as _, Seek as _, SeekFrom, Write as _}, fs::{File, OpenOptions}, + io::{Read as _, Seek as _, SeekFrom, Write as _}, marker::PhantomData, path::PathBuf, }; @@ -8,7 +8,11 @@ use std::{ use generic_array::typenum::{U16, U512}; use littlefs2::{const_ram_storage, driver::Storage}; -use crate::{store, store::Store, types::{LfsResult, LfsStorage}}; +use crate::{ + store, + store::Store, + types::{LfsResult, LfsStorage}, +}; pub trait StoreProvider { type Store: Store; @@ -52,10 +56,7 @@ impl Storage for FilesystemStorage { } fn write(&mut self, offset: usize, data: &[u8]) -> LfsResult { - let mut file = OpenOptions::new() - .write(true) - .open(&self.0) - .unwrap(); + let mut file = OpenOptions::new().write(true).open(&self.0).unwrap(); file.seek(SeekFrom::Start(offset as _)).unwrap(); let bytes_written = file.write(data).unwrap(); assert_eq!(bytes_written, data.len()); @@ -64,10 +65,7 @@ impl Storage for FilesystemStorage { } fn erase(&mut self, offset: usize, len: usize) -> LfsResult { - let mut file = OpenOptions::new() - .write(true) - .open(&self.0) - .unwrap(); + let mut file = OpenOptions::new().write(true).open(&self.0).unwrap(); file.seek(SeekFrom::Start(offset as _)).unwrap(); let zero_block = [0xFFu8; Self::BLOCK_SIZE]; for _ in 0..(len / Self::BLOCK_SIZE) { @@ -79,17 +77,16 @@ impl Storage for FilesystemStorage { } } -store!(FilesystemStore, - Internal: FilesystemStorage, - External: ExternalStorage, - Volatile: VolatileStorage +store!( + FilesystemStore, + Internal: FilesystemStorage, + External: ExternalStorage, + Volatile: VolatileStorage ); impl Default for FilesystemStore { fn default() -> Self { - Self { - __: PhantomData, - } + Self { __: PhantomData } } } @@ -111,10 +108,7 @@ impl Filesystem { file.set_len(len).expect("failed to set storage file len"); true }; - Self { - internal, - format, - } + Self { internal, format } } } @@ -122,9 +116,7 @@ impl StoreProvider for Filesystem { type Store = FilesystemStore; unsafe fn store(&self) -> Self::Store { - Self::Store { - __: PhantomData, - } + Self::Store { __: PhantomData } } unsafe fn reset(&self) { @@ -135,15 +127,24 @@ impl StoreProvider for Filesystem { Self::Store::allocate(ifs, efs, vfs); let format = self.format; self.store() - .mount(ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage, format) + .mount( + ifs_alloc, + ifs_storage, + efs_alloc, + efs_storage, + vfs_alloc, + vfs_storage, + format, + ) .expect("failed to mount filesystem"); } } -store!(RamStore, - Internal: InternalStorage, - External: ExternalStorage, - Volatile: VolatileStorage +store!( + RamStore, + Internal: InternalStorage, + External: ExternalStorage, + Volatile: VolatileStorage ); #[derive(Copy, Clone, Debug, Default)] @@ -153,9 +154,7 @@ impl StoreProvider for Ram { type Store = RamStore; unsafe fn store(&self) -> Self::Store { - Self::Store { - __: PhantomData, - } + Self::Store { __: PhantomData } } unsafe fn reset(&self) { @@ -165,7 +164,15 @@ impl StoreProvider for Ram { let (ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage) = Self::Store::allocate(ifs, efs, vfs); self.store() - .mount(ifs_alloc, ifs_storage, efs_alloc, efs_storage, vfs_alloc, vfs_storage, true) + .mount( + ifs_alloc, + ifs_storage, + efs_alloc, + efs_storage, + vfs_alloc, + vfs_storage, + true, + ) .expect("failed to mount filesystem"); } } diff --git a/src/virt/ui.rs b/src/virt/ui.rs index fcc23d3775f..541a0498e55 100644 --- a/src/virt/ui.rs +++ b/src/virt/ui.rs @@ -1,5 +1,5 @@ -use std::time::{Duration, Instant}; use crate::platform::{self, consent::Level, reboot::To, ui::Status}; +use std::time::{Duration, Instant}; pub struct UserInterface { start_time: Instant, @@ -51,7 +51,7 @@ impl platform::UserInterface for UserInterface { if let Some(inner) = &mut self.inner { inner.reboot(to); } else { - loop { + loop { continue; } } diff --git a/tests/attest.rs b/tests/attest.rs index fc1bef550af..13d84bea95c 100644 --- a/tests/attest.rs +++ b/tests/attest.rs @@ -5,7 +5,6 @@ // use trussed::types::Location::*; - // tests not working as no setup of the attn keys in place // tests were valid for previous implementation using self-signed certificates diff --git a/tests/certificate.rs b/tests/certificate.rs index a8e04f407ed..55eeeea4c67 100644 --- a/tests/certificate.rs +++ b/tests/certificate.rs @@ -2,11 +2,7 @@ mod client; -use trussed::{ - client::CertificateClient as _, - syscall, try_syscall, - types::Location::*, -}; +use trussed::{client::CertificateClient as _, syscall, try_syscall, types::Location::*}; #[test] fn certificate_client() { diff --git a/tests/counter.rs b/tests/counter.rs index 84d73a43c10..8c94fc0038f 100644 --- a/tests/counter.rs +++ b/tests/counter.rs @@ -3,11 +3,7 @@ mod client; mod store; -use trussed::{ - client::CounterClient as _, - syscall, - types::Location::*, -}; +use trussed::{client::CounterClient as _, syscall, types::Location::*}; // #[test] // fn counter_implementation() { @@ -36,7 +32,6 @@ use trussed::{ #[test] fn counter_client() { client::get(|client| { - let id = syscall!(client.create_counter(Volatile)).id; assert_eq!(syscall!(client.increment_counter(id)).counter, 0); assert_eq!(syscall!(client.increment_counter(id)).counter, 1); @@ -54,6 +49,5 @@ fn counter_client() { for j in 2..1_000 { assert_eq!(syscall!(client.increment_counter(jd)).counter, j); } - }); } diff --git a/tests/p256.rs b/tests/p256.rs index a130899c02d..52b8ad18176 100644 --- a/tests/p256.rs +++ b/tests/p256.rs @@ -7,7 +7,6 @@ mod client; use trussed::types::Location::*; - #[test] fn p256_agree() { client::get(|client| { diff --git a/tests/store/mod.rs b/tests/store/mod.rs index 1f0e1cf6254..5ea456783c5 100644 --- a/tests/store/mod.rs +++ b/tests/store/mod.rs @@ -7,18 +7,15 @@ const_ram_storage!(InternalStorage, 8192); const_ram_storage!(ExternalStorage, 8192); const_ram_storage!(VolatileStorage, 8192); -trussed::store!(Store, +trussed::store!( + Store, Internal: InternalStorage, External: ExternalStorage, Volatile: VolatileStorage ); #[allow(dead_code)] -pub fn get( - test: impl FnOnce(&mut Store) -> R - ) - -> R -{ +pub fn get(test: impl FnOnce(&mut Store) -> R) -> R { let mut store = init_store(); test(&mut store) } diff --git a/tests/virt.rs b/tests/virt.rs index 70931a399f7..93f2dbb8217 100644 --- a/tests/virt.rs +++ b/tests/virt.rs @@ -3,8 +3,8 @@ use std::time::Duration; use trussed::{ client::{FilesystemClient as _, ManagementClient as _}, - types::{Bytes, Location, PathBuf}, syscall, + types::{Bytes, Location, PathBuf}, virt, }; @@ -16,7 +16,11 @@ fn run_test(data: u8) { virt::with_ram_client("test", |mut client| { // ensure that the filesystem is empty let read_dir = syscall!(client.read_dir_first(location, PathBuf::from(""), None)).entry; - assert!(read_dir.is_none(), "Filesystem not empty: {:?}", read_dir.unwrap()); + assert!( + read_dir.is_none(), + "Filesystem not empty: {:?}", + read_dir.unwrap() + ); // ensure that no other client is messing with our filesystem while syscall!(client.uptime()).uptime < Duration::from_secs(1) { diff --git a/tests/x255.rs b/tests/x255.rs index 0697b6bee35..84957f0b889 100644 --- a/tests/x255.rs +++ b/tests/x255.rs @@ -7,7 +7,6 @@ mod client; use trussed::types::Location::*; - #[test] fn x255_agree() { client::get(|client| {