From 01728a5a5cdd825835a1bea00807b8a8e080e2b8 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Fri, 20 Dec 2024 11:54:04 +0100 Subject: [PATCH] Update dependencies for trussed-core and ctaphid-app --- Cargo.toml | 16 ++-- components/encrypted_container/Cargo.toml | 2 +- .../encrypted_container/src/container.rs | 13 ++-- components/encrypted_container/src/error.rs | 22 +++--- fuzz/Cargo.toml | 11 +-- src/authenticator.rs | 73 +++++++++++-------- src/calculate.rs | 14 ++-- src/credential.rs | 2 +- src/ctaphid.rs | 34 +++------ src/state.rs | 30 ++++---- 10 files changed, 110 insertions(+), 107 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6462f9b49..647f38720 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,17 +9,17 @@ description = "Secrets App - a Trussed app to manage OTP and Password Safe featu [dependencies] apdu-app = { version = "0.1", optional = true } -ctaphid-dispatch = { version = "0.1", optional = true } +ctaphid-app = { version = "0.1.0-rc.1", optional = true } cbor-smol = "0.5" delog = "0.1.6" -flexiber = { version = "0.1.0", features = ["derive", "heapless"] } +flexiber = { version = "0.1.1", features = ["derive", "heapless"] } heapless = "0.7" heapless-bytes = "0.3" hex-literal = "0.3" iso7816 = "0.1.3" littlefs2-core = "0.1" serde = { version = "1", default-features = false } -trussed = { version = "0.1", features = ["clients-3"] } +trussed-core = { version = "0.1.0-rc.1", features = ["chacha8-poly1305", "crypto-client", "hmac-sha1", "hmac-sha256", "filesystem-client", "sha256", "ui-client"] } encrypted_container = { path = "components/encrypted_container" } block-padding = "0.3.3" bitflags = "2.3.1" @@ -27,10 +27,14 @@ bitflags = "2.3.1" # extension trussed-auth = "0.3.0" +[dev-dependencies] +trussed = { version = "0.1", default-features = false, features = ["clients-3"] } + [features] default = ["apdu-dispatch"] devel = ["apdu-dispatch", "log-all", "delog/std-log", "devel-counters"] apdu-dispatch = ["dep:apdu-app"] +ctaphid-dispatch = ["dep:ctaphid-app"] # Count accesses to the read-only and read-write persistence storage devel-counters = [] @@ -52,7 +56,5 @@ log-warn = [] log-error = [] [patch.crates-io] -ctaphid-dispatch = { git = "https://github.com/Nitrokey/ctaphid-dispatch", tag = "v0.1.1-nitrokey.2" } -flexiber = { git = "https://github.com/Nitrokey/flexiber", tag = "0.1.1.nitrokey" } -trussed = { git = "https://github.com/trussed-dev/trussed", rev = "046478b7a4f6e2315acf9112d98308379c2e3eee" } -trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "c030b82ad3441f337af09afe3a69e8a6da5785ea" } +trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "6bba8fde36d05c0227769eb63345744e87d84b2b" } +trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "fc53539536d7658c45a492585041742d8cdc45d0" } diff --git a/components/encrypted_container/Cargo.toml b/components/encrypted_container/Cargo.toml index 7ddfd050c..0415ff7ff 100644 --- a/components/encrypted_container/Cargo.toml +++ b/components/encrypted_container/Cargo.toml @@ -11,7 +11,7 @@ description = "Universal AEAD Encrypted Container, using CBOR and Chacha8Poly130 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -trussed = { version = "0.1" } +trussed-core = { version = "0.1.0-rc.1", features = ["chacha8-poly1305", "crypto-client"] } heapless = "0.7" heapless-bytes = "0.3" serde = { version = "1", default-features = false } diff --git a/components/encrypted_container/src/container.rs b/components/encrypted_container/src/container.rs index 2b20151fa..6037b4dfa 100644 --- a/components/encrypted_container/src/container.rs +++ b/components/encrypted_container/src/container.rs @@ -6,8 +6,9 @@ use cbor_smol::{cbor_deserialize, cbor_serialize}; use heapless_bytes::Bytes; use serde::de::DeserializeOwned; use serde::Serialize; -use trussed::{ +use trussed_core::{ try_syscall, + mechanisms::Chacha8Poly1305, types::{KeyId, Message}, }; @@ -110,7 +111,7 @@ impl EncryptedDataContainer { encryption_key: KeyId, ) -> Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, O: DeserializeOwned, { let deserialized_container: EncryptedDataContainer = @@ -127,7 +128,7 @@ impl EncryptedDataContainer { encryption_key: KeyId, ) -> Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, O: Serialize, { let message = Message::try_from(|buf| { @@ -148,7 +149,7 @@ impl EncryptedDataContainer { encryption_key: KeyId, ) -> Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, { #[cfg(dangerous_disable_encryption)] { @@ -187,7 +188,7 @@ impl EncryptedDataContainer { encryption_key: KeyId, ) -> Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, O: DeserializeOwned, { let message = self @@ -204,7 +205,7 @@ impl EncryptedDataContainer { encryption_key: KeyId, ) -> Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, { if self.data.is_empty() { return Err(Error::EmptyContainerData); diff --git a/components/encrypted_container/src/error.rs b/components/encrypted_container/src/error.rs index 58a0ac8c3..cfe65386b 100644 --- a/components/encrypted_container/src/error.rs +++ b/components/encrypted_container/src/error.rs @@ -18,25 +18,25 @@ pub enum Error { pub type Result = core::result::Result; -impl From for trussed::error::Error { +impl From for trussed_core::Error { fn from(e: Error) -> Self { match e { Error::DeserializationToContainerError => { - trussed::error::Error::InvalidSerializationFormat + trussed_core::Error::InvalidSerializationFormat } Error::DeserializationToObjectError => { - trussed::error::Error::InvalidSerializationFormat + trussed_core::Error::InvalidSerializationFormat } - Error::ObjectSerializationError => trussed::error::Error::InvalidSerializationFormat, - Error::ContainerSerializationError => trussed::error::Error::InvalidSerializationFormat, - Error::SerializationBufferTooSmall => trussed::error::Error::InternalError, - Error::FailedEncryption => trussed::error::Error::InternalError, + Error::ObjectSerializationError => trussed_core::Error::InvalidSerializationFormat, + Error::ContainerSerializationError => trussed_core::Error::InvalidSerializationFormat, + Error::SerializationBufferTooSmall => trussed_core::Error::InternalError, + Error::FailedEncryption => trussed_core::Error::InternalError, Error::FailedContainerSerialization => { - trussed::error::Error::InvalidSerializationFormat + trussed_core::Error::InvalidSerializationFormat } - Error::EmptyContainerData => trussed::error::Error::WrongMessageLength, - Error::FailedDecryption => trussed::error::Error::InvalidSerializationFormat, - Error::EmptyDecryptedData => trussed::error::Error::WrongMessageLength, + Error::EmptyContainerData => trussed_core::Error::WrongMessageLength, + Error::FailedDecryption => trussed_core::Error::InvalidSerializationFormat, + Error::EmptyDecryptedData => trussed_core::Error::WrongMessageLength, } } } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index dbcee1085..0ffbcec2f 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -54,15 +54,8 @@ doc = false [patch.crates-io] -flexiber = { git = "https://github.com/Nitrokey/flexiber", tag = "0.1.1.nitrokey" } apdu-dispatch = { git = "https://github.com/trussed-dev/apdu-dispatch.git", rev = "915fc237103fcecc29d0f0b73391f19abf6576de" } - -# forked -trussed = { git = "https://github.com/trussed-dev/trussed", rev = "046478b7a4f6e2315acf9112d98308379c2e3eee" } - -# unreleased upstream changes ctaphid-dispatch = { git = "https://github.com/Nitrokey/ctaphid-dispatch", tag = "v0.1.1-nitrokey.2" } -serde-indexed = { git = "https://github.com/nitrokey/serde-indexed.git", tag = "v0.1.0-nitrokey.2" } +trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "6bba8fde36d05c0227769eb63345744e87d84b2b" } +trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "fc53539536d7658c45a492585041742d8cdc45d0" } -# unreleased crates -trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "c030b82ad3441f337af09afe3a69e8a6da5785ea" } diff --git a/src/authenticator.rs b/src/authenticator.rs index 9128cdf50..05627b5f9 100644 --- a/src/authenticator.rs +++ b/src/authenticator.rs @@ -11,10 +11,14 @@ use core::time::Duration; use flexiber::EncodableHeapless; use heapless_bytes::Bytes; use iso7816::{Data, Status}; -use littlefs2_core::path; -use trussed::types::Location; -use trussed::types::{KeyId, Message}; -use trussed::{self, client, syscall, try_syscall}; +use littlefs2_core::{path, PathBuf}; +use trussed_core::types::Location; +use trussed_core::types::{KeyId, Message}; +use trussed_core::{ + mechanisms::{Chacha8Poly1305, HmacSha1, HmacSha256, Sha256}, + CryptoClient, FilesystemClient, UiClient, +}; +use trussed_core::{syscall, try_syscall}; use crate::calculate::hmac_challenge; use crate::command::CredentialData::HmacData; @@ -31,6 +35,31 @@ use crate::{ #[cfg(feature = "brute-force-delay")] use crate::REQUIRED_DELAY_ON_FAILED_VERIFICATION; +/// The requirements for the Trussed client. +pub trait Client: + CryptoClient + + FilesystemClient + + UiClient + + HmacSha1 + + HmacSha256 + + Sha256 + + Chacha8Poly1305 + + trussed_auth::AuthClient +{ +} + +impl Client for T where + T: CryptoClient + + FilesystemClient + + UiClient + + HmacSha1 + + HmacSha256 + + Sha256 + + Chacha8Poly1305 + + trussed_auth::AuthClient +{ +} + /// The options for the authenticator app. #[derive(Clone, Copy, Debug)] #[non_exhaustive] @@ -205,17 +234,9 @@ impl AnswerToSelect { } } -impl Authenticator -where - T: client::Client - + client::HmacSha1 - + client::HmacSha256 - + client::Sha256 - + client::Chacha8Poly1305 - + trussed_auth::AuthClient, -{ - fn credential_directory() -> trussed::types::PathBuf { - trussed::types::PathBuf::from(path!("cred")) +impl Authenticator { + fn credential_directory() -> PathBuf { + PathBuf::from(path!("cred")) } /// Create new Authenticator instance @@ -401,9 +422,7 @@ where for loc in [Location::External, Location::Internal, Location::Volatile] { info_now!(":: reset - delete all keys and files in {:?}", loc); let _r1 = try_syscall!(self.trussed.delete_all(loc)); - let _r2 = try_syscall!(self - .trussed - .remove_dir_all(loc, trussed::types::PathBuf::new())); + let _r2 = try_syscall!(self.trussed.remove_dir_all(loc, PathBuf::new())); debug_now!(":: reset - results {:?} {:?}", _r1, _r2); } @@ -672,7 +691,7 @@ where } } - fn filename_for_label(&mut self, label: &[u8]) -> trussed::types::PathBuf { + fn filename_for_label(&mut self, label: &[u8]) -> PathBuf { let label_hash = syscall!(self.trussed.hash_sha256(label)).hash; // todo: maybe use a counter instead (put it in our persistent state). @@ -683,7 +702,7 @@ where hex_filename[2 * i + 1] = LOOKUP[(value & 0xF) as usize]; } - let filename = trussed::types::PathBuf::try_from(hex_filename.as_ref()).unwrap(); + let filename = PathBuf::try_from(hex_filename.as_ref()).unwrap(); let mut path = Self::credential_directory(); path.push(&filename); info_now!("filename: {}", path.as_str_ref_with_trailing_nul()); @@ -1124,7 +1143,7 @@ where Ok(()) } - fn _debug_trussed_backend_error(_e: trussed::Error, _l: u32) -> Status { + fn _debug_trussed_backend_error(_e: trussed_core::Error, _l: u32) -> Status { info_now!("Trussed backend error: {:?} (line {:?})", _e, _l); Status::UnspecifiedNonpersistentExecutionError } @@ -1229,7 +1248,7 @@ where use crate::UP_TIMEOUT_MILLISECONDS; let result = syscall!(self.trussed.confirm_user_present(UP_TIMEOUT_MILLISECONDS)).result; result.map_err(|err| match err { - trussed::types::consent::Error::TimedOut => Status::SecurityStatusNotSatisfied, + trussed_core::types::consent::Error::TimedOut => Status::SecurityStatusNotSatisfied, _ => Status::UnspecifiedPersistentExecutionError, }) } @@ -1358,15 +1377,7 @@ impl iso7816::App for Authenticator { } #[cfg(feature = "apdu-dispatch")] -impl apdu_app::App for Authenticator -where - T: client::Client - + client::HmacSha1 - + client::HmacSha256 - + client::Sha256 - + client::Chacha8Poly1305 - + trussed_auth::AuthClient, -{ +impl apdu_app::App for Authenticator { fn select( &mut self, _interface: iso7816::Interface, diff --git a/src/calculate.rs b/src/calculate.rs index d60647377..51f7ade1a 100644 --- a/src/calculate.rs +++ b/src/calculate.rs @@ -8,15 +8,17 @@ use iso7816::Status; use crate::oath; use crate::Result; -use trussed::types::Signature; -use trussed::{ - client, try_syscall, +use trussed_core::types::Signature; +use trussed_core::{ + mechanisms::{HmacSha1, HmacSha256}, + try_syscall, types::{KeyId, Location}, + CryptoClient, }; fn with_key(trussed: &mut T, key: &[u8], f: F) -> Result where - T: client::Client, + T: CryptoClient, F: FnOnce(&mut T, KeyId) -> O, { let injected = try_syscall!(trussed.unsafe_inject_shared_key(key, Location::Volatile,)) @@ -40,7 +42,7 @@ pub fn calculate( key: &[u8], ) -> Result<[u8; 4]> where - T: client::Client + client::HmacSha1 + client::HmacSha256 + client::Sha256, + T: HmacSha1 + HmacSha256, { with_key(trussed, key, |trussed, key| { use oath::Algorithm::*; @@ -71,7 +73,7 @@ pub fn hmac_challenge( key: &[u8], ) -> Result where - T: client::Client + client::HmacSha1, + T: HmacSha1, { with_key(trussed, key, |trussed, key| { use oath::Algorithm::*; diff --git a/src/credential.rs b/src/credential.rs index 7d4b4deba..91249fcf8 100644 --- a/src/credential.rs +++ b/src/credential.rs @@ -11,7 +11,7 @@ use crate::command::{ use crate::oath::{Algorithm, Kind}; use iso7816::Status; use serde::{Deserialize, Serialize}; -use trussed::types::ShortData; +use trussed_core::types::ShortData; #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct CredentialFlat { diff --git a/src/ctaphid.rs b/src/ctaphid.rs index 26f250f7f..52afd23ac 100644 --- a/src/ctaphid.rs +++ b/src/ctaphid.rs @@ -3,22 +3,14 @@ // // SPDX-License-Identifier: Apache-2.0 OR MIT -use crate::Authenticator; -use ctaphid_dispatch::app::{self, Command as HidCommand, Message}; -use ctaphid_dispatch::command::VendorCommand; +use crate::{authenticator::Client, Authenticator}; +use ctaphid_app::{App, Command as HidCommand, Error, VendorCommand}; +use heapless_bytes::Bytes; use iso7816::Status; -use trussed::{client, interrupt::InterruptFlag}; +use trussed_core::InterruptFlag; pub const OTP_CCID: VendorCommand = VendorCommand::H70; -impl app::App<'static> for Authenticator -where - T: trussed::Client - + client::HmacSha1 - + client::HmacSha256 - + client::Sha256 - + client::Chacha8Poly1305 - + trussed_auth::AuthClient, -{ +impl App<'static, N> for Authenticator { fn commands(&self) -> &'static [HidCommand] { &[HidCommand::Vendor(OTP_CCID)] } @@ -26,20 +18,18 @@ where fn call( &mut self, command: HidCommand, - input_data: &Message, - response: &mut Message, - ) -> app::AppResult { + input_data: &[u8], + response: &mut Bytes, + ) -> Result<(), Error> { match command { HidCommand::Vendor(OTP_CCID) => { let arr: [u8; 2] = Status::Success.into(); response.extend(arr); - let ctap_to_iso7816_command = iso7816::command::CommandView::try_from( - input_data.as_slice(), - ) - .map_err(|_e| { + let ctap_to_iso7816_command = iso7816::command::CommandView::try_from(input_data) + .map_err(|_e| { response.clear(); info_now!("ISO conversion error: {:?}", _e); - app::Error::InvalidLength + Error::InvalidLength })?; let res = self.respond(ctap_to_iso7816_command, response); @@ -59,7 +49,7 @@ where } } _ => { - return Err(app::Error::InvalidCommand); + return Err(Error::InvalidCommand); } } Ok(()) diff --git a/src/state.rs b/src/state.rs index 2bf2d1164..f7dac6457 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,19 +7,20 @@ use core::convert::TryInto; use core::time::Duration; use iso7816::Status; -use littlefs2_core::path; +use littlefs2_core::{path, Path, PathBuf}; use serde::de::DeserializeOwned; use serde::Serialize; use crate::command::EncryptionKeyType; use cbor_smol::cbor_deserialize; use encrypted_container::EncryptedDataContainer; -use trussed::client::FilesystemClient; -use trussed::types::Message; -use trussed::{ +use trussed_core::mechanisms::Chacha8Poly1305; +use trussed_core::types::Message; +use trussed_core::{ syscall, try_syscall, - types::{KeyId, Location, Path, PathBuf}, + types::{KeyId, Location}, }; +use trussed_core::{CryptoClient, FilesystemClient}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct State { @@ -97,7 +98,7 @@ impl State { encryption_key_type: Option, ) -> crate::Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: FilesystemClient + Chacha8Poly1305, O: Serialize, { let encryption_key = self @@ -127,7 +128,7 @@ impl State { fn get_encryption_key_from_state( &mut self, encryption_key_type: Option, - ) -> trussed::error::Result { + ) -> trussed_core::Result { // Try to read cached field (should not be empty if unlocked) let key = match encryption_key_type.unwrap_or(EncryptionKeyType::Hardware) { EncryptionKeyType::Hardware => self.runtime.encryption_key_hardware, @@ -139,7 +140,7 @@ impl State { encryption_key_type ); } - key.ok_or(trussed::Error::NoSuchKey) + key.ok_or(trussed_core::Error::NoSuchKey) } pub fn decrypt_content( @@ -148,7 +149,7 @@ impl State { ser_encrypted: Message, ) -> (encrypted_container::Result, Option) where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: Chacha8Poly1305, O: DeserializeOwned, { // We do not know what key was used for encryption @@ -194,9 +195,9 @@ impl State { &mut self, trussed: &mut T, filename: PathBuf, - ) -> trussed::error::Result + ) -> trussed_core::Result where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: FilesystemClient + Chacha8Poly1305, O: DeserializeOwned, { let ser_encrypted = try_syscall!(trussed.read_file(self.location, filename))?.data; @@ -213,7 +214,7 @@ impl State { f: impl FnOnce(&mut T, &Persistent) -> X, ) -> X where - T: trussed::Client + trussed::client::Chacha8Poly1305, + T: CryptoClient + FilesystemClient, { let state = self.get_persistent_or_default(trussed); @@ -227,7 +228,10 @@ impl State { f(trussed, &state) } - fn get_persistent_or_default(&self, trussed: &mut impl trussed::Client) -> Persistent { + fn get_persistent_or_default( + &self, + trussed: &mut C, + ) -> Persistent { // 1. If there is serialized, persistent state (i.e., the try_syscall! to `read_file` does // not fail), then assume it is valid and deserialize it. If the reading fails, assume // that this is the first run, and set defaults.