diff --git a/keyfork-shard/src/openpgp/smartcard.rs b/keyfork-shard/src/openpgp/smartcard.rs index 9de6c27..de37f38 100644 --- a/keyfork-shard/src/openpgp/smartcard.rs +++ b/keyfork-shard/src/openpgp/smartcard.rs @@ -1,6 +1,6 @@ -use std::{collections::HashSet}; +use std::collections::{HashMap, HashSet}; -use keyfork_prompt::{Error as PromptError, DefaultPromptManager, default_prompt_manager}; +use keyfork_prompt::{default_prompt_manager, DefaultPromptManager, Error as PromptError}; use super::openpgp::{ self, @@ -65,6 +65,7 @@ pub struct SmartcardManager { current_card: Option>, root: Option, pm: DefaultPromptManager, + pin_cache: HashMap, } impl SmartcardManager { @@ -73,6 +74,7 @@ impl SmartcardManager { current_card: None, root: None, pm: default_prompt_manager()?, + pin_cache: Default::default(), }) } @@ -217,12 +219,13 @@ impl DecryptionHelper for &mut SmartcardManager { .application_identifier() .context("Could not load application identifier")? .ident(); - let mut pin = None; + let mut pin = self.pin_cache.get(&fp).cloned(); while transaction .pw_status_bytes() .map_err(Error::PwStatusBytes)? .err_count_pw1() > 0 + && pin.is_none() { transaction.reload_ard()?; let attempts = transaction @@ -236,12 +239,11 @@ impl DecryptionHelper for &mut SmartcardManager { format!("Unlock card {card_id} ({cardholder_name})\n{rpea}: {attempts}\n\nPIN: ") }; let temp_pin = self.pm.prompt_passphrase(&message)?; - let verification_status = - transaction.verify_user_pin(temp_pin.as_str().trim()); + let verification_status = transaction.verify_user_pin(temp_pin.as_str().trim()); match verification_status { Ok(_) => { + self.pin_cache.insert(fp.clone(), temp_pin.clone()); pin.replace(temp_pin); - break; } Err(CardError::CardStatus(StatusBytes::IncorrectParametersCommandDataField)) => { self.pm.prompt_message("Invalid PIN length entered.")?;