Skip to content

Commit

Permalink
Implement optimization migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Mar 7, 2024
1 parent 08e64f5 commit e16757b
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 42 deletions.
18 changes: 10 additions & 8 deletions Cargo.lock

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

16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ version = "1.7.0-rc.1"
memory-regions = { path = "components/memory-regions" }

# forked
admin-app = { git = "https://github.com/Nitrokey/admin-app.git", tag = "v0.1.0-nitrokey.10" }
cbor-smol = { git = "https://github.com/Nitrokey/cbor-smol.git", tag = "v0.4.0-nitrokey.1" }
fido-authenticator = { git = "https://github.com/Nitrokey/fido-authenticator.git", tag = "v0.1.1-nitrokey.12" }
admin-app = { git = "https://github.com/Nitrokey/admin-app.git", rev = "c584a1911ab65670729ea068fe54e0bae7f2459e" }
cbor-smol = { git = "https://github.com/Nitrokey/cbor-smol.git", rev = "bac1ac69dd0117d1f80f3f5e1d3b60ba8987ad70"}
fido-authenticator = { git = "https://github.com/Nitrokey/fido-authenticator.git", rev = "a3757fb1b5d8c9d0485ca7f3524caed7b629dc04" }
flexiber = { git = "https://github.com/Nitrokey/flexiber", tag = "0.1.1.nitrokey" }
lpc55-hal = { git = "https://github.com/Nitrokey/lpc55-hal", tag = "v0.3.0-nitrokey.2" }
serde-indexed = { git = "https://github.com/nitrokey/serde-indexed.git", tag = "v0.1.0-nitrokey.2" }
trussed = { git = "https://github.com/Nitrokey/trussed.git", tag = "v0.1.0-nitrokey.18" }
trussed = { git = "https://github.com/Nitrokey/trussed.git", rev = "371e8f7a07817c2ed57978bd86e3412bd9877647" }

# unreleased upstream changes
apdu-dispatch = { git = "https://github.com/Nitrokey/apdu-dispatch.git", tag = "v0.1.2-nitrokey.3" }
ctap-types = { git = "https://github.com/trussed-dev/ctap-types.git", rev = "a9f8003a1d9f05f9eea39e615b9159bc0613fcb5" }
ctaphid-dispatch = { git = "https://github.com/Nitrokey/ctaphid-dispatch.git", tag = "v0.1.1-nitrokey.3" }
littlefs2 = { git = "https://github.com/trussed-dev/littlefs2", rev = "ebd27e49ca321089d01d8c9b169c4aeb58ceeeca" }
littlefs2 = { git = "https://github.com/nitrokey/littlefs2.git", rev = "99b1a9832c46c9097e73ca1fa43e119026e2068f" }
usbd-ctaphid = { git = "https://github.com/trussed-dev/usbd-ctaphid.git", rev = "1db2e014f28669bc484c81ab0406c54b16bba33c" }
usbd-ccid = { git = "https://github.com/Nitrokey/usbd-ccid", tag = "v0.2.0-nitrokey.1" }
p256-cortex-m4 = { git = "https://github.com/ycrypto/p256-cortex-m4.git", rev = "cdb31e12594b4dc1f045b860a885fdc94d96aee2" }
Expand All @@ -39,12 +39,12 @@ secrets-app = { git = "https://github.com/Nitrokey/trussed-secrets-app", tag = "
webcrypt = { git = "https://github.com/nitrokey/nitrokey-websmartcard-rust", rev = "b1502d72035ecde0f16f9fff5c8da06139b90d11" }
opcard = { git = "https://github.com/Nitrokey/opcard-rs", rev = "1c844b74aa5bf245cd8223bc63b74b3a1f1f7b0f" }
piv-authenticator = { git = "https://github.com/Nitrokey/piv-authenticator", tag = "v0.3.4" }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", rev = "fdb0dd29bccaf6ec2385b664abc50e4c523ca83e" }
trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", rev = "4b8191f248c26cb074cdac887c7f3f48f9c449a4" }
trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", rev = "97e5557bbfb126c0f0a2367ed928aab4c1469043" }
trussed-hkdf = { git = "https://github.com/Nitrokey/trussed-hkdf-backend.git", tag = "v0.1.0" }
trussed-auth = { git = "https://github.com/Nitrokey/trussed-auth", rev = "7ad0ab1f592dabb3646840cbb11769a988166fb4" }
trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend.git", rev = "9732a9a3e98af72112286afdc9b7174c66c2869a" }
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.2.0" }
trussed-se050-backend = { git = "https://github.com/Nitrokey/trussed-se050-backend.git", rev = "393bff2ead093f3a043c3e04ed7a706649f66b7f" }

[profile.release]
codegen-units = 1
Expand Down
3 changes: 2 additions & 1 deletion components/apps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ webcrypt = ["dep:webcrypt", "backend-auth", "backend-rsa", "backend-webcrypt-hma
fido-authenticator = ["dep:fido-authenticator", "usbd-ctaphid"]
opcard = ["dep:opcard", "backend-rsa", "backend-auth"]
piv-authenticator = ["dep:piv-authenticator", "backend-rsa", "backend-auth"]
se050 = ["dep:se05x", "trussed-se050-backend", "admin-app/se050"]
se050 = ["dep:se05x", "trussed-se050-backend", "admin-app/se050", "se050-migration"]
se050-migration = ["dep:se05x", "trussed-se050-backend"]

# backends
backend-auth = ["trussed-auth"]
Expand Down
43 changes: 43 additions & 0 deletions components/apps/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ use trussed_staging::{
StagingBackend, StagingContext,
};

#[cfg(any(
feature = "fido-authenticator",
feature = "se050-migration",
feature = "backend-auth"
))]
use trussed_staging::manage::Migrator;

#[cfg(feature = "webcrypt")]
#[cfg(feature = "backend-webcrypt-hmacsha256p256")]
use webcrypt::hmacsha256p256::{
Backend as HmacSha256P256Backend, BackendContext as HmacSha256P256Context,
Expand Down Expand Up @@ -92,9 +100,44 @@ fn should_preserve_file(file: &Path) -> bool {
}
}

pub(crate) const MIGRATION_VERSION_SPACE_EFFICIENCY: u32 = 1;

fn build_staging_backend() -> StagingBackend {
let mut backend = StagingBackend::new();
backend.manage.should_preserve_file = |file, _location| should_preserve_file(file);
backend.manage.migrators = &[
// We first migrate the SE050 since this migration deletes data to make sure that the other
// migrations succeed even on low block availability
#[cfg(feature = "se050-migration")]
Migrator {
migrate: |ifs, _efs| {
trussed_se050_backend::migrate::migrate_remove_all_dat(ifs, &[path!("/opcard")])
},
version: MIGRATION_VERSION_SPACE_EFFICIENCY,
},
#[cfg(feature = "backend-auth")]
Migrator {
migrate: |ifs, _efs| {
trussed_auth::migrate::migrate_remove_dat(
ifs,
&[
path!("opcard"),
path!("webcrypt"),
path!("secrets"),
path!("piv"),
],
)
},
version: MIGRATION_VERSION_SPACE_EFFICIENCY,
},
#[cfg(feature = "fido-authenticator")]
Migrator {
migrate: |ifs, _efs| {
fido_authenticator::migrate::migrate_no_rp_dir(ifs, path!("/fido/dat"))
},
version: MIGRATION_VERSION_SPACE_EFFICIENCY,
},
];
backend
}

Expand Down
80 changes: 55 additions & 25 deletions components/apps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub struct Config {
fido: FidoConfig,
#[serde(default, rename = "o", skip_serializing_if = "is_default")]
opcard: OpcardConfig,
#[serde(default, rename = "v", skip_serializing_if = "is_default")]
fs_version: u32,
}

impl admin_app::Config for Config {
Expand Down Expand Up @@ -74,6 +76,14 @@ impl admin_app::Config for Config {
None
}
}

fn migration_version(&self) -> Option<u32> {
Some(self.fs_version)
}
fn set_migration_version(&mut self, version: u32) -> bool {
self.fs_version = version;
true
}
}

#[derive(Debug, Default, PartialEq, Deserialize, Serialize)]
Expand All @@ -82,7 +92,7 @@ pub struct FidoConfig {
disable_skip_up_timeout: bool,
}

impl admin_app::Config for FidoConfig {
impl FidoConfig {
fn field(&mut self, key: &str) -> Option<ConfigValueMut<'_>> {
match key {
"disable_skip_up_timeout" => {
Expand All @@ -92,6 +102,7 @@ impl admin_app::Config for FidoConfig {
}
}

#[cfg(feature = "factory-reset")]
fn reset_client_id(
&self,
_key: &str,
Expand Down Expand Up @@ -132,7 +143,7 @@ impl OpcardConfig {
}
}

impl admin_app::Config for OpcardConfig {
impl OpcardConfig {
fn field(&mut self, key: &str) -> Option<ConfigValueMut<'_>> {
match key {
#[cfg(feature = "se050")]
Expand All @@ -141,6 +152,7 @@ impl admin_app::Config for OpcardConfig {
}
}

#[cfg(feature = "factory-reset")]
fn reset_client_id(
&self,
key: &str,
Expand Down Expand Up @@ -306,6 +318,12 @@ impl<R: Runner> Apps<R> {
}
}

/// Return false if the migration failed.
pub fn ensure_migrated(&mut self) -> bool {
const LATEST_MIGRATION: u32 = dispatch::MIGRATION_VERSION_SPACE_EFFICIENCY;
self.admin.migrate(LATEST_MIGRATION).is_ok()
}

fn admin_app(
runner: &R,
make_client: impl FnOnce(
Expand Down Expand Up @@ -337,6 +355,7 @@ impl<R: Runner> Apps<R> {
data.status(),
)
});

(app, data.init_status)
}

Expand Down Expand Up @@ -369,27 +388,31 @@ impl<R: Runner> Apps<R> {
let mut apps: Vec<&mut dyn ApduApp<ApduCommandSize, ApduResponseSize>, 7> =
Default::default();

let migrated_successfuly = self.ensure_migrated();

// App 1: ndef
#[cfg(feature = "ndef-app")]
apps.push(&mut self.ndef).ok().unwrap();

// App 2: secrets
#[cfg(feature = "secrets-app")]
apps.push(&mut self.oath).ok().unwrap();
if migrated_successfuly {
// App 2: secrets
#[cfg(feature = "secrets-app")]
apps.push(&mut self.oath).ok().unwrap();

// App 3: opcard
#[cfg(feature = "opcard")]
if let Some(opcard) = &mut self.opcard {
apps.push(opcard).ok().unwrap();
}
// App 3: opcard
#[cfg(feature = "opcard")]
if let Some(opcard) = &mut self.opcard {
apps.push(opcard).ok().unwrap();
}

// App 4: piv
#[cfg(feature = "piv-authenticator")]
apps.push(&mut self.piv).ok().unwrap();
// App 4: piv
#[cfg(feature = "piv-authenticator")]
apps.push(&mut self.piv).ok().unwrap();

// App 5: fido
#[cfg(all(feature = "fido-authenticator", not(feature = "webcrypt")))]
apps.push(&mut self.fido).ok().unwrap();
// App 5: fido
#[cfg(all(feature = "fido-authenticator", not(feature = "webcrypt")))]
apps.push(&mut self.fido).ok().unwrap();
}

// App 6: admin
apps.push(&mut self.admin).ok().unwrap();
Expand All @@ -407,18 +430,24 @@ impl<R: Runner> Apps<R> {
{
let mut apps: Vec<&mut dyn CtaphidApp<'static>, 4> = Default::default();

// App 1: webcrypt or fido
#[cfg(feature = "webcrypt")]
apps.push(&mut self.webcrypt).ok().unwrap();
#[cfg(all(feature = "fido-authenticator", not(feature = "webcrypt")))]
apps.push(&mut self.fido).ok().unwrap();
let migrated_successfuly = self.ensure_migrated();

if migrated_successfuly {
// App 1: webcrypt or fido
#[cfg(feature = "webcrypt")]
apps.push(&mut self.webcrypt).ok().unwrap();
#[cfg(all(feature = "fido-authenticator", not(feature = "webcrypt")))]
apps.push(&mut self.fido).ok().unwrap();
}

// App 2: admin
apps.push(&mut self.admin).ok().unwrap();

// App 3: secrets
#[cfg(feature = "secrets-app")]
apps.push(&mut self.oath).ok().unwrap();
if migrated_successfuly {
// App 3: secrets
#[cfg(feature = "secrets-app")]
apps.push(&mut self.oath).ok().unwrap();
}

// App 4: provisioner
#[cfg(feature = "provisioner-app")]
Expand Down Expand Up @@ -462,7 +491,7 @@ impl<R: Runner> trussed_usbip::Apps<'static, Client<R>, Dispatch> for Apps<R> {
trait App<R: Runner>: Sized {
/// additional data needed by this Trussed app
type Data;
type Config: admin_app::Config;
type Config;

/// the desired client ID
const CLIENT_ID: &'static str;
Expand Down Expand Up @@ -845,6 +874,7 @@ mod tests {
#[cfg(feature = "se050")]
use_se050_backend: true,
},
fs_version: 1,
};
let data: Bytes<1024> = cbor_serialize_bytes(&config).unwrap();
// littlefs2 is most efficient with files < 1/4 of the block size. The block sizes are 512
Expand Down

0 comments on commit e16757b

Please sign in to comment.