Add command to list configuration options

This commit is contained in:
Sosthène Guédon
2024-10-03 11:06:36 +02:00
committed by Robin Krahl
parent 29a48fea31
commit c5bddba53d
4 changed files with 69 additions and 4 deletions
+2 -1
View File
@@ -11,7 +11,7 @@ description = "Administrative Trussed app for SoloKeys Solo 2 security keys"
[dependencies]
apdu-dispatch = "0.1"
cbor-smol = "0.4.0"
cbor-smol = { version = "0.4.0", features = ["heapless-v0-7", "heapless-bytes-v0-3"] }
ctaphid-dispatch = "0.1"
delog = "0.1"
iso7816 = "0.1"
@@ -48,3 +48,4 @@ littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "ebd27
trussed = { git = "https://github.com/Nitrokey/trussed.git", tag = "v0.1.0-nitrokey.18" }
trussed-manage = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "manage-v0.1.0" }
trussed-se050-manage = { git = "https://github.com/Nitrokey/trussed-se050-backend.git", tag = "se050-manage-v0.1.0" }
cbor-smol = { git = "https://github.com/trussed-dev/cbor-smol.git", rev = "4a368461e06e3ca52d79638b9ab8f34b038491fc" }
+8 -1
View File
@@ -1,7 +1,7 @@
use super::Client as TrussedClient;
use apdu_dispatch::iso7816::Status;
use apdu_dispatch::{app as apdu, command, dispatch::Interface, response, Command as ApduCommand};
use cbor_smol::cbor_deserialize;
use cbor_smol::{cbor_deserialize, cbor_serialize_to};
use core::{convert::TryInto, marker::PhantomData, time::Duration};
use ctaphid_dispatch::app::{self as hid, Command as HidCommand, Message};
use ctaphid_dispatch::command::VendorCommand;
@@ -28,6 +28,7 @@ const SET_CONFIG: u8 = 0x83;
const FACTORY_RESET: u8 = 0x84;
#[cfg(feature = "factory-reset")]
const FACTORY_RESET_APP: u8 = 0x85;
const LIST_AVAILABLE_FIELDS: u8 = 0x86;
// For compatibility, old commands are also available directly as separate vendor commands.
const UPDATE: VendorCommand = VendorCommand::H51;
@@ -69,6 +70,7 @@ enum Command {
FactoryReset,
#[cfg(feature = "factory-reset")]
FactoryResetApp,
ListAvailableFields,
}
impl TryFrom<u8> for Command {
@@ -92,6 +94,7 @@ impl TryFrom<u8> for Command {
FACTORY_RESET => Ok(Command::FactoryReset),
#[cfg(feature = "factory-reset")]
FACTORY_RESET_APP => Ok(Command::FactoryResetApp),
LIST_AVAILABLE_FIELDS => Ok(Command::ListAvailableFields),
_ => Err(Error::UnsupportedCommand),
}
}
@@ -426,6 +429,10 @@ where
};
response.push(status).ok();
}
Command::ListAvailableFields => {
cbor_serialize_to(&self.config.list_available_fields(), response).ok();
return Ok(());
}
#[cfg(feature = "factory-reset")]
Command::FactoryReset => {
debug_now!("Factory resetting the device");
+57 -1
View File
@@ -20,7 +20,7 @@ use trussed::{
///
/// It is expected to have one such structure for each application supporting factory-reset by the admin-app
///
/// ```rust
/// ```rust,ignore
///# use admin_app::{ResetSignalAllocation, ConfigValueMut};
///# use littlefs2::{path::Path, path};
/// #[derive(Default, PartialEq, serde::Deserialize, serde::Serialize)]
@@ -163,6 +163,34 @@ pub trait Config: Default + PartialEq + DeserializeOwned + Serialize {
///
/// Return false if the configuration does not support storing the migration version
fn set_migration_version(&mut self, _version: u32) -> bool;
fn list_available_fields(&self) -> &'static [ConfigField];
}
// No need to rename, cbor-smol already packs enum using ids
#[derive(Serialize)]
#[non_exhaustive]
pub enum FieldType {
Bool,
U8,
}
#[derive(Serialize)]
pub struct ConfigField {
#[serde(rename = "n")]
pub name: &'static str,
/// Changing the config field requires a touch
#[serde(rename = "c")]
pub requires_touch_confirmation: bool,
/// Changing the config field requires a power cycle
#[serde(rename = "r")]
pub requires_reboot: bool,
/// Changing the config field deletes data
#[serde(rename = "d")]
pub destructive: bool,
/// The type of data stored in this field
#[serde(rename = "t")]
pub ty: FieldType,
}
impl Config for () {
@@ -181,6 +209,10 @@ impl Config for () {
fn set_migration_version(&mut self, _version: u32) -> bool {
false
}
fn list_available_fields(&self) -> &'static [ConfigField] {
&[]
}
}
#[derive(Debug, Serialize)]
@@ -313,3 +345,27 @@ fn load_if_exists<F: Filestore>(
}
})
}
#[cfg(test)]
mod tests {
use hex_literal::hex;
use super::*;
#[test]
fn config_field() {
let fields = &[ConfigField {
name: "test_name",
requires_touch_confirmation: true,
requires_reboot: false,
destructive: true,
ty: FieldType::Bool,
}];
let mut bytes: trussed::types::Vec<u8, 100> = Default::default();
cbor_smol::cbor_serialize_to(fields, &mut bytes).unwrap();
assert_eq!(
&bytes,
&hex!("81A5616E69746573745F6E616D656163F56172F46164F5617400")
);
}
}
+2 -1
View File
@@ -16,7 +16,8 @@ pub mod migrations;
pub use admin::{App, Reboot, StatusBytes};
pub use config::{
Config, ConfigError, ConfigValueMut, ResetConfigResult, ResetSignal, ResetSignalAllocation,
Config, ConfigError, ConfigField, ConfigValueMut, FieldType, ResetConfigResult, ResetSignal,
ResetSignalAllocation,
};
use trussed_manage::ManageClient;
#[cfg(feature = "se050")]