diff --git a/Cargo.lock b/Cargo.lock index 2d531c51..7323a965 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ version = 3 [[package]] name = "admin-app" version = "0.1.0" -source = "git+https://github.com/Nitrokey/admin-app.git?rev=4e9e7bd9cd83c729b78c23f738fb05d559b06ab9#4e9e7bd9cd83c729b78c23f738fb05d559b06ab9" +source = "git+https://github.com/Nitrokey/admin-app.git?rev=1adbce18ca884d35a3a4b80a7c5dd8fca9e4bae0#1adbce18ca884d35a3a4b80a7c5dd8fca9e4bae0" dependencies = [ "apdu-dispatch", "cbor-smol", @@ -114,6 +114,8 @@ dependencies = [ "embedded-hal", "fido-authenticator", "hex", + "if_chain", + "littlefs2", "ndef-app", "opcard", "piv-authenticator", @@ -1658,6 +1660,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + [[package]] name = "indexmap" version = "1.9.3" @@ -1778,8 +1786,7 @@ checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" [[package]] name = "littlefs2" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95c72bdf63e7ad35f391e60c48e4c32560038f1d3a0dd97f90a2891ce09160bf" +source = "git+https://github.com/trussed-dev/littlefs2?rev=e6c46e7ba5ae19129e457a2182e40a439c0322fe#e6c46e7ba5ae19129e457a2182e40a439c0322fe" dependencies = [ "bitflags 1.3.2", "cstr_core", diff --git a/Cargo.toml b/Cargo.toml index 88fabd09..daa5d90d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ version = "1.6.0-rc.1" [patch.crates-io] # forked -admin-app = { git = "https://github.com/Nitrokey/admin-app.git", rev = "4e9e7bd9cd83c729b78c23f738fb05d559b06ab9" } +admin-app = { git = "https://github.com/Nitrokey/admin-app.git", rev = "1adbce18ca884d35a3a4b80a7c5dd8fca9e4bae0" } ctap-types = { git = "https://github.com/Nitrokey/ctap-types", tag = "v0.1.2-nitrokey.4" } fido-authenticator = { git = "https://github.com/Nitrokey/fido-authenticator.git", tag = "v0.1.1-nitrokey.8" } flexiber = { git = "https://github.com/Nitrokey/flexiber", tag = "0.1.1.nitrokey" } @@ -26,6 +26,7 @@ iso7816 = { git = "https://github.com/Nitrokey/iso7816.git", tag = "v0.1.1-nitro trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "d97c64d0bc5f83ce22b0e0ed034a2b451616b3f9" } usbd-ctaphid = { git = "https://github.com/Nitrokey/usbd-ctaphid.git", tag = "v0.1.0-nitrokey.2" } usbd-ccid = { git = "https://github.com/Nitrokey/usbd-ccid", tag = "v0.2.0-nitrokey.1" } +littlefs2 = { git = "https://github.com/trussed-dev/littlefs2", rev = "e6c46e7ba5ae19129e457a2182e40a439c0322fe" } # unreleased crates secrets-app = { git = "https://github.com/Nitrokey/trussed-secrets-app", tag = "v0.13.0-rc2" } @@ -33,8 +34,8 @@ webcrypt = { git = "https://github.com/nitrokey/nitrokey-websmartcard-rust", tag opcard = { git = "https://github.com/Nitrokey/opcard-rs", tag = "v1.2.0" } piv-authenticator = { git = "https://github.com/Nitrokey/piv-authenticator", tag = "v0.3.3" } se05x = { git = "https://github.com/Nitrokey/se05x.git", tag = "v0.1.0"} -trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "1826aaee72da5e539c35aa6d9fbc036c30c94d6f" } -trussed-rsa-alloc = { git = "https://github.com/Nitrokey/trussed-rsa-backend.git", rev = "2f51478f0861ff8db19fdd5290f023ab6f4c2fb9" } +trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "62235294bd63977bbb88eb01e7ac44b8010eb450" } +trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend.git", rev = "2f51478f0861ff8db19fdd5290f023ab6f4c2fb9" } trussed-staging = { git = "https://github.com/nitrokey/trussed-staging.git", branch = "hmacsha256p256-rebased" } trussed-usbip = { git = "https://github.com/Nitrokey/pc-usbip-runner.git", tag = "v0.0.1-nitrokey.3" } trussed-se050-backend = { git = "https://github.com/Nitrokey/trussed-se050-backend.git", tag = "v0.1.0-test-driver" } diff --git a/components/apps/Cargo.toml b/components/apps/Cargo.toml index 4be43338..95675645 100644 --- a/components/apps/Cargo.toml +++ b/components/apps/Cargo.toml @@ -11,6 +11,8 @@ trussed = { version = "0.1", features = ["serde-extensions"]} trussed-usbip = { version = "0.0.1", default-features = false, features = ["ctaphid"], optional = true } usbd-ctaphid = { version = "0.1", optional = true } utils = { path = "../utils" } +if_chain = "1.0.2" +littlefs2 = { version = "0.4" } # Backends trussed-auth = { version = "0.2.2", optional = true } diff --git a/components/apps/src/dispatch.rs b/components/apps/src/dispatch.rs index 28017602..8f3f5497 100644 --- a/components/apps/src/dispatch.rs +++ b/components/apps/src/dispatch.rs @@ -9,6 +9,9 @@ use trussed::{ Platform, }; +use littlefs2::{path, path::Path}; + +use if_chain::if_chain; use trussed::{ api::{reply, request}, backend::Backend as _, @@ -21,7 +24,9 @@ use embedded_hal::blocking::delay::DelayUs; #[cfg(feature = "se050")] use se05x::{se05x::Se05X, t1::I2CForT1}; #[cfg(feature = "se050")] -use trussed_se050_backend::{manage::ManageExtension as Se050ManageExtension , Context as Se050Context, Se050Backend}; +use trussed_se050_backend::{ + manage::ManageExtension as Se050ManageExtension, Context as Se050Context, Se050Backend, +}; #[cfg(feature = "backend-auth")] use trussed_auth::{AuthBackend, AuthContext, AuthExtension, MAX_HW_KEY_LEN}; @@ -30,9 +35,8 @@ use trussed_auth::{AuthBackend, AuthContext, AuthExtension, MAX_HW_KEY_LEN}; use trussed_rsa_alloc::SoftwareRsa; use trussed_staging::{ - streaming::ChunkedExtension, wrap_key_to_file::WrapKeyToFileExtension, StagingBackend, - manage::ManageExtension, - StagingContext, + manage::ManageExtension, streaming::ChunkedExtension, wrap_key_to_file::WrapKeyToFileExtension, + StagingBackend, StagingContext, }; #[cfg(feature = "webcrypt")] @@ -57,31 +61,31 @@ pub struct DispatchContext { se050: Se050Context, } +fn should_preserve_file(file: &Path) -> bool { + // We save all "special" objects, with an ID that is representable by a `u8` + + const DIRS: &[&Path] = &[path!("x5c"), path!("ctr"), path!("sec"), path!("pub")]; + + let mut components = file.iter(); + if_chain! { + if components.next() == Some("/".into()); + if components.next().is_some(); + if let Some(intermediary) = components.next(); + if DIRS.contains(&&*intermediary); + if let Some(file_name) = components.next(); + if components.next().is_none(); + if file_name.as_ref().len() <=2; + then { + true + } else { + false + } + } +} + fn build_staging_backend() -> StagingBackend { let mut backend = StagingBackend::new(); - backend.manage.should_preserve_file = |file, location| { - // // We save all "special" objects, with an ID that is representable by a `u8` - - // let Some(parent) = file.parent() else { - // return false; - // }; - - // if &[path!("x5c"), path!("sss")] - - // let Some(root) = parent.parent() else { - // return false; - // }; - - // if root.parent.is_some() { - // return false; - // } - - - // const PATHS_TO_SAVE: &[&Path] = &[path!("/fido/x5c/00"), path!("fido/sec/00")]; - - // // if PATHS_TO_SAVE.contains() - false - }; + backend.manage.should_preserve_file = |file, _location| should_preserve_file(file); backend } @@ -95,7 +99,7 @@ impl Dispatch { Self { #[cfg(feature = "backend-auth")] auth: AuthBackend::new(auth_location), - staging: StagingBackend::new(), + staging: build_staging_backend(), #[cfg(feature = "se050")] se050: se050.map(trussed_se050_backend::Se050Backend::new), #[cfg(not(feature = "se050"))] @@ -111,7 +115,7 @@ impl Dispatch { ) -> Self { Self { auth: AuthBackend::with_hw_key(auth_location, hw_key), - staging: StagingBackend::new(), + staging: build_staging_backend(), #[cfg(feature = "se050")] se050: se050.map(trussed_se050_backend::Se050Backend::new), #[cfg(not(feature = "se050"))] @@ -165,6 +169,7 @@ impl ExtensionDispatch for Dispatch { self.staging .request(&mut ctx.core, &mut ctx.backends.staging, request, resources) } + Backend::StagingManage => Err(TrussedError::RequestNotAvailable), #[cfg(feature = "se050")] Backend::Se050 => self .se050 @@ -229,17 +234,27 @@ impl ExtensionDispatch for Dispatch { #[allow(unreachable_patterns)] _ => Err(TrussedError::RequestNotAvailable), }, + Backend::StagingManage => match extension { + Extension::Manage => ExtensionImpl::::extension_request_serialized( + &mut self.staging, + &mut ctx.core, + &mut ctx.backends.staging, + request, + resources, + ), + _ => Err(TrussedError::RequestNotAvailable), + }, #[cfg(feature = "se050")] Backend::Se050 => match extension { - Extension::Se050Manage => { - ExtensionImpl::::extension_request_serialized( - self.se050.as_mut().ok_or(TrussedError::GeneralError)?, - &mut ctx.core, - &mut ctx.backends.se050, - request, - resources, - ) - } + Extension::Se050Manage => ExtensionImpl::< + trussed_se050_backend::manage::ManageExtension, + >::extension_request_serialized( + self.se050.as_mut().ok_or(TrussedError::GeneralError)?, + &mut ctx.core, + &mut ctx.backends.se050, + request, + resources, + ), _ => Err(TrussedError::RequestNotAvailable), }, _ => Err(TrussedError::RequestNotAvailable), @@ -254,6 +269,7 @@ pub enum Backend { #[cfg(feature = "backend-rsa")] SoftwareRsa, Staging, + StagingManage, #[cfg(feature = "se050")] Se050, } @@ -344,3 +360,17 @@ impl ExtensionId for Dispatch { const ID: Self::Id = Self::Id::Se050Manage; } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn file_preserve() { + assert!(should_preserve_file(path!("/fido/sec/00"))); + assert!(should_preserve_file(path!("/fido/x5c/00"))); + assert!(should_preserve_file(path!("/fido/sec/01"))); + assert!(should_preserve_file(path!("/fido/x5c/01"))); + assert!(!should_preserve_file(path!("/fido/dat/sec/00"))); + } +} diff --git a/components/apps/src/lib.rs b/components/apps/src/lib.rs index ee671a72..d3035c17 100644 --- a/components/apps/src/lib.rs +++ b/components/apps/src/lib.rs @@ -15,11 +15,11 @@ use embedded_hal::blocking::delay::DelayUs; use serde::{Deserialize, Serialize}; use trussed::{ backend::BackendId, client::ClientBuilder, interrupt::InterruptFlag, platform::Syscall, - store::filestore::ClientFilestore, ClientImplementation, Platform, Service, + store::filestore::ClientFilestore, types::Path, ClientImplementation, Platform, Service, }; -use admin_app::ConfigValueMut; pub use admin_app::Reboot; +use admin_app::{ConfigValueMut, ResetSignalAllocation}; use trussed::types::Location; #[cfg(feature = "webcrypt")] @@ -47,6 +47,18 @@ impl admin_app::Config for Config { _ => None, } } + + fn reset_client_id(&self, _key: &str) -> Option<&'static Path> { + None + } + + fn reset_signal(&self, _key: &str) -> Option<&'static ResetSignalAllocation> { + None + } + + fn can_reset(&self, _client: &str) -> Option<&'static ResetSignalAllocation> { + None + } } #[derive(Debug, Default, PartialEq, Deserialize, Serialize)] @@ -422,6 +434,7 @@ impl App for AdminApp { fn backends(runner: &R, _config: &()) -> &'static [BackendId] { const BACKENDS_ADMIN: &[BackendId] = &[ + BackendId::Custom(Backend::StagingManage), #[cfg(feature = "se050-test-app")] BackendId::Custom(Backend::Se050), BackendId::Core,