mirror of
https://github.com/solokeys/admin-app.git
synced 2026-06-20 13:16:17 -07:00
Add command to list configuration options
This commit is contained in:
committed by
Robin Krahl
parent
29a48fea31
commit
c5bddba53d
+2
-1
@@ -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
@@ -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
@@ -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
@@ -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")]
|
||||
|
||||
Reference in New Issue
Block a user