From fc4a8e12af694a40fe17bcebddd9e4617075400f Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Sun, 30 Dec 2018 18:39:31 +0100 Subject: Implement the pin unblock subcommand This patch implements the pin unblock command that unblocks and resets the user PIN. The name unblock is chosen over libnitrokey's unlock to be consistent with the GnuPG terminology and to avoid confusion with the unrelated lock command. --- nitrocli/src/commands.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'nitrocli/src/commands.rs') diff --git a/nitrocli/src/commands.rs b/nitrocli/src/commands.rs index 7f25415..e3e2a14 100644 --- a/nitrocli/src/commands.rs +++ b/nitrocli/src/commands.rs @@ -474,6 +474,50 @@ pub fn pin_clear() -> Result<()> { Ok(()) } +fn check_pin(pintype: pinentry::PinType, pin: &str) -> Result<()> { + let minimum_length = match pintype { + pinentry::PinType::Admin => 8, + pinentry::PinType::User => 6, + }; + if pin.len() < minimum_length { + Err(Error::Error(format!( + "The PIN must be at least {} characters long", + minimum_length + ))) + } else { + Ok(()) + } +} + +fn choose_pin(pintype: pinentry::PinType) -> Result { + pinentry::clear_passphrase(pintype)?; + let new_pin = pinentry::inquire_passphrase(pintype, pinentry::Mode::Choose, None)?; + pinentry::clear_passphrase(pintype)?; + let new_pin = String::from_utf8(new_pin)?; + check_pin(pintype, &new_pin)?; + + let confirm_pin = pinentry::inquire_passphrase(pintype, pinentry::Mode::Confirm, None)?; + pinentry::clear_passphrase(pintype)?; + let confirm_pin = String::from_utf8(confirm_pin)?; + + if new_pin != confirm_pin { + Err(Error::Error("Entered PINs do not match".to_string())) + } else { + Ok(new_pin) + } +} + +/// Unblock and reset the user PIN. +pub fn pin_unblock() -> Result<()> { + let device = get_device()?; + let user_pin = choose_pin(pinentry::PinType::User)?; + try_with_passphrase( + pinentry::PinType::Admin, + "Could not unblock the user PIN", + |admin_pin| device.unlock_user_pin(&admin_pin, &user_pin), + ) +} + #[cfg(test)] mod tests { use super::*; -- cgit v1.2.1