summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2017-04-09 19:36:35 -0700
committerDaniel Mueller <deso@posteo.net>2017-04-09 19:36:35 -0700
commitf94d04578f44fc79212550203838f7c78e1ac414 (patch)
tree903bdcdd5edde580a557509ec55acfd1a5edad0f
parentc441df2c153c811af19f37bdfdc45a13c36e8f14 (diff)
downloadnitrocli-f94d04578f44fc79212550203838f7c78e1ac414.tar.gz
nitrocli-f94d04578f44fc79212550203838f7c78e1ac414.tar.bz2
Add 'status' command
The nitrokey supports a status command that instructs it to report details about itself. This data includes general useful information such as the current version of the firmware being installed along with more contextual bits such as the number of remaining retries for the user and admin PINs or whether the different volumes (unencrypted, encrypted, hidden) are writable. This change introduces the 'status' command line option that can be used to retrieve this information from the nitrokey and to display it.
-rw-r--r--nitrocli/README.md15
-rw-r--r--nitrocli/src/main.rs82
-rw-r--r--nitrocli/src/nitrokey.rs5
3 files changed, 101 insertions, 1 deletions
diff --git a/nitrocli/README.md b/nitrocli/README.md
index 5ec814e..69f9b8c 100644
--- a/nitrocli/README.md
+++ b/nitrocli/README.md
@@ -7,6 +7,7 @@ certain commands on the [Nitrokey Storage][nitrokey] device.
The following commands are currently supported:
- open: Open the encrypted volume. The user PIN needs to be entered.
- close: Close the encrypted volume.
+- status: Report status information about the Nitrokey.
Usage
@@ -17,6 +18,20 @@ parameter, e.g.:
```bash
# Open the nitrokey's encrypted volume.
$ nitrocli open
+
+$ nitrocli status
+Status:
+ SD card ID: 0xdeadbeef
+ firmware version: 44.0
+ firmware: unlocked
+ storage keys: created
+ user retry count: 3
+ admin retry count: 3
+ volumes:
+ unencrypted: active
+ encrypted: active
+ hidden: inactive
+
# Close it again.
$ nitrocli close
```
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index 32ecb3a..92aa79e 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -148,6 +148,86 @@ fn nitrokey_do(function: &NitroFunc) -> Result<()> {
}
+/// Pretty print the response of a status command.
+fn print_status(response: &nitrokey::DeviceStatusResponse) {
+ println!("Status:");
+ // We omit displaying information about the smartcard here as this
+ // program really is only about the SD card portion of the device.
+ println!(" SD card ID: {:#x}", response.active_sdcard_id);
+ println!(" firmware version: {}.{}",
+ response.version_major,
+ response.version_minor);
+ println!(" firmware: {}",
+ if response.firmware_locked != 0 {
+ "locked".to_string()
+ } else {
+ "unlocked".to_string()
+ });
+ println!(" storage keys: {}",
+ if response.storage_keys_missing == 0 {
+ "created".to_string()
+ } else {
+ "not created".to_string()
+ });
+ println!(" user retry count: {}",
+ response.user_password_retry_count);
+ println!(" admin retry count: {}",
+ response.admin_password_retry_count);
+ println!(" volumes:");
+ println!(" unencrypted: {}",
+ if response.volume_active & nitrokey::VOLUME_ACTIVE_UNENCRYPTED == 0 {
+ "inactive"
+ } else if response.unencrypted_volume_read_only != 0 {
+ "read-only"
+ } else {
+ "active"
+ });
+ println!(" encrypted: {}",
+ if response.volume_active & nitrokey::VOLUME_ACTIVE_ENCRYPTED == 0 {
+ "inactive"
+ } else if response.encrypted_volume_read_only != 0 {
+ "read-only"
+ } else {
+ "active"
+ });
+ println!(" hidden: {}",
+ if response.volume_active & nitrokey::VOLUME_ACTIVE_HIDDEN == 0 {
+ "inactive"
+ } else if response.hidden_volume_read_only != 0 {
+ "read-only"
+ } else {
+ "active"
+ });
+}
+
+
+/// Inquire the status of the nitrokey.
+fn status() -> Result<()> {
+ type Response = nitrokey::Response<nitrokey::DeviceStatusResponse>;
+
+ return nitrokey_do(&|handle| {
+ let payload = nitrokey::DeviceStatusCommand::new();
+ let report = nitrokey::Report::from(payload);
+
+ let report = transmit::<_, nitrokey::EmptyPayload>(handle, &report)?;
+ let response = &AsRef::<Response>::as_ref(&report.data).data;
+
+ // TODO: We should probably check the success of the command as
+ // well.
+ if response.magic != nitrokey::MAGIC_NUMBER_STICK20_CONFIG {
+ let error = format!("Status response contains invalid magic: {:#x} \
+ (expected: {:#x})",
+ response.magic,
+ nitrokey::MAGIC_NUMBER_STICK20_CONFIG);
+ return Err(Error::Error(error.to_string()));
+ }
+
+ print_status(response);
+ return Ok(());
+ });
+}
+
+
/// Open the encrypted volume on the nitrokey.
fn open() -> Result<()> {
return nitrokey_do(&|handle| {
@@ -203,7 +283,7 @@ fn run() -> i32 {
return 1;
}
- commands!(&argv[1], [open, close]);
+ commands!(&argv[1], [open, close, status]);
}
fn main() {
diff --git a/nitrocli/src/nitrokey.rs b/nitrocli/src/nitrokey.rs
index d5e21be..d1d6c72 100644
--- a/nitrocli/src/nitrokey.rs
+++ b/nitrocli/src/nitrokey.rs
@@ -30,6 +30,11 @@ pub const PID: u16 = 0x4109;
// Magic number identifying a storage response.
pub const MAGIC_NUMBER_STICK20_CONFIG: u16 = 0x3318;
+// Flags indicating whether the respective volume is active or not.
+pub const VOLUME_ACTIVE_UNENCRYPTED: u8 = 0b001;
+pub const VOLUME_ACTIVE_ENCRYPTED: u8 = 0b010;
+pub const VOLUME_ACTIVE_HIDDEN: u8 = 0b100;
+
#[derive(Debug)]
#[derive(PartialEq)]