aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nitrocli/src/error.rs4
-rw-r--r--nitrocli/src/main.rs68
-rw-r--r--nitrocli/src/pinentry.rs17
3 files changed, 41 insertions, 48 deletions
diff --git a/nitrocli/src/error.rs b/nitrocli/src/error.rs
index 1b7068d..d755cac 100644
--- a/nitrocli/src/error.rs
+++ b/nitrocli/src/error.rs
@@ -21,7 +21,6 @@ use std::fmt;
use std::io;
use std::string;
-
#[derive(Debug)]
pub enum Error {
IoError(io::Error),
@@ -29,21 +28,18 @@ pub enum Error {
Error(String),
}
-
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error::IoError(e)
}
}
-
impl From<string::FromUtf8Error> for Error {
fn from(e: string::FromUtf8Error) -> Error {
Error::Utf8Error(e)
}
}
-
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs
index 8a8405a..c190d1b 100644
--- a/nitrocli/src/main.rs
+++ b/nitrocli/src/main.rs
@@ -54,7 +54,7 @@
unused_qualifications,
unused_results,
where_clauses_object_safety,
- while_true,
+ while_true
)]
#![warn(
bad_style,
@@ -62,7 +62,7 @@
nonstandard_style,
renamed_and_removed_lints,
rust_2018_compatibility,
- rust_2018_idioms,
+ rust_2018_idioms
)]
//! Nitrocli is a program providing a command line interface to certain
@@ -82,13 +82,11 @@ type Result<T> = result::Result<T, Error>;
const PIN_TYPE: pinentry::PinType = pinentry::PinType::User;
-
/// Create an `error::Error` with an error message of the format `msg: err`.
fn get_error(msg: &str, err: &nitrokey::CommandError) -> Error {
Error::Error(format!("{}: {:?}", msg, err))
}
-
/// Connect to a Nitrokey Storage device and return it.
fn get_storage_device() -> Result<nitrokey::Storage> {
nitrokey::Storage::connect()
@@ -108,37 +106,43 @@ fn get_volume_status(status: &nitrokey::VolumeStatus) -> &'static str {
}
}
-
/// Pretty print the response of a status command.
fn print_status(status: &nitrokey::StorageStatus) {
- 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}", status.serial_number_sd_card);
- println!(" firmware version: {}.{}",
- status.firmware_version_major,
- status.firmware_version_minor);
- println!(" firmware: {}",
- if status.firmware_locked {
- "locked".to_string()
- } else {
- "unlocked".to_string()
- });
- println!(" storage keys: {}",
- if status.stick_initialized {
- "created".to_string()
- } else {
- "not created".to_string()
- });
- println!(" user retry count: {}", status.user_retry_count);
- println!(" admin retry count: {}", status.admin_retry_count);
- println!(" volumes:");
- println!(" unencrypted: {}", get_volume_status(&status.unencrypted_volume));
- println!(" encrypted: {}", get_volume_status(&status.encrypted_volume));
- println!(" hidden: {}", get_volume_status(&status.hidden_volume));
+ println!(
+ r#"Status:
+ SD card ID: {id:#x}
+ firmware version: {fwv0}.{fwv1}
+ firmware: {fw}
+ storage keys: {sk}
+ user retry count: {urc}
+ admin retry count: {arc}
+ volumes:
+ unencrypted: {vu}
+ encrypted: {ve}
+ hidden: {vh}"#,
+ id = status.serial_number_sd_card,
+ fwv0 = status.firmware_version_major,
+ fwv1 = status.firmware_version_minor,
+ fw = if status.firmware_locked {
+ "locked"
+ } else {
+ "unlocked"
+ },
+ sk = if status.stick_initialized {
+ "created"
+ } else {
+ "not created"
+ },
+ urc = status.user_retry_count,
+ arc = status.admin_retry_count,
+ vu = get_volume_status(&status.unencrypted_volume),
+ ve = get_volume_status(&status.encrypted_volume),
+ vh = get_volume_status(&status.hidden_volume),
+ );
}
-
/// Inquire the status of the nitrokey.
fn status() -> Result<()> {
let status = get_storage_device()?
@@ -149,7 +153,6 @@ fn status() -> Result<()> {
Ok(())
}
-
/// Open the encrypted volume on the nitrokey.
fn open() -> Result<()> {
let device = get_storage_device()?;
@@ -174,14 +177,13 @@ fn open() -> Result<()> {
}
let error = "Opening encrypted volume failed: Wrong password";
return Err(Error::Error(error.to_string()));
- },
+ }
err => return Err(get_error("Opening encrypted volume failed", &err)),
},
};
}
}
-
#[link(name = "c")]
extern "C" {
fn sync();
@@ -200,13 +202,11 @@ fn close() -> Result<()> {
.map_err(|err| get_error("Closing encrypted volume failed", &err))
}
-
/// Clear the PIN stored when opening the nitrokey's encrypted volume.
fn clear() -> Result<()> {
pinentry::clear_passphrase(PIN_TYPE)
}
-
// A macro for generating a match of the different supported commands.
// Each supplied command is converted into a string and matched against.
macro_rules! commands {
diff --git a/nitrocli/src/pinentry.rs b/nitrocli/src/pinentry.rs
index 66ca6be..fc7af2c 100644
--- a/nitrocli/src/pinentry.rs
+++ b/nitrocli/src/pinentry.rs
@@ -21,7 +21,6 @@ use std::process;
use crate::error::Error;
-
/// PIN type requested from pinentry.
///
/// The available PIN types correspond to the PIN types used by the Nitrokey devices: user and
@@ -35,7 +34,6 @@ pub enum PinType {
User,
}
-
impl PinType {
fn cache_id(self) -> &'static str {
match self {
@@ -59,7 +57,6 @@ impl PinType {
}
}
-
fn parse_pinentry_passphrase(response: Vec<u8>) -> Result<Vec<u8>, Error> {
let string = String::from_utf8(response)?;
let lines: Vec<&str> = string.lines().collect();
@@ -84,14 +81,15 @@ fn parse_pinentry_passphrase(response: Vec<u8>) -> Result<Vec<u8>, Error> {
Err(Error::Error("Unexpected response: ".to_string() + &string))
}
-
/// Inquire a PIN of the given type from the user.
///
/// This function inquires a PIN of the given type from the user or returns the cached passphrase,
/// if available. If an error message is set, it is displayed in the passphrase dialog.
pub fn inquire_passphrase(pin_type: PinType, error_msg: Option<&str>) -> Result<Vec<u8>, Error> {
let cache_id = pin_type.cache_id();
- let error_msg = error_msg.map(|msg| msg.replace(" ", "+")).unwrap_or_else(|| String::from("+"));
+ let error_msg = error_msg
+ .map(|msg| msg.replace(" ", "+"))
+ .unwrap_or_else(|| String::from("+"));
let prompt = pin_type.prompt();
let description = pin_type.description().replace(" ", "+");
@@ -103,13 +101,13 @@ pub fn inquire_passphrase(pin_type: PinType, error_msg: Option<&str>) -> Result<
// reported for the GET_PASSPHRASE command does not actually cause
// gpg-connect-agent to exit with a non-zero error code, we have to
// evaluate the output to determine success/failure.
- let output = process::Command::new("gpg-connect-agent").arg(command)
+ let output = process::Command::new("gpg-connect-agent")
+ .arg(command)
.arg("/bye")
.output()?;
parse_pinentry_passphrase(output.stdout)
}
-
fn parse_pinentry_response(response: Vec<u8>) -> Result<(), Error> {
let string = String::from_utf8(response)?;
let lines: Vec<&str> = string.lines().collect();
@@ -121,18 +119,17 @@ fn parse_pinentry_response(response: Vec<u8>) -> Result<(), Error> {
Err(Error::Error("Unexpected response: ".to_string() + &string))
}
-
/// Clear the cached passphrase of the given type.
pub fn clear_passphrase(pin_type: PinType) -> Result<(), Error> {
let command = "CLEAR_PASSPHRASE ".to_string() + pin_type.cache_id();
- let output = process::Command::new("gpg-connect-agent").arg(command)
+ let output = process::Command::new("gpg-connect-agent")
+ .arg(command)
.arg("/bye")
.output()?;
parse_pinentry_response(output.stdout)
}
-
#[cfg(test)]
mod tests {
use super::*;