keyfork-shard: add PIN cache

This commit is contained in:
Ryan Heywood 2023-12-26 15:17:33 -05:00
parent ddefe1c6b5
commit 726670fe96
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
1 changed files with 8 additions and 6 deletions

View File

@ -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::{ use super::openpgp::{
self, self,
@ -65,6 +65,7 @@ pub struct SmartcardManager {
current_card: Option<Card<Open>>, current_card: Option<Card<Open>>,
root: Option<Cert>, root: Option<Cert>,
pm: DefaultPromptManager, pm: DefaultPromptManager,
pin_cache: HashMap<Fingerprint, String>,
} }
impl SmartcardManager { impl SmartcardManager {
@ -73,6 +74,7 @@ impl SmartcardManager {
current_card: None, current_card: None,
root: None, root: None,
pm: default_prompt_manager()?, pm: default_prompt_manager()?,
pin_cache: Default::default(),
}) })
} }
@ -217,12 +219,13 @@ impl DecryptionHelper for &mut SmartcardManager {
.application_identifier() .application_identifier()
.context("Could not load application identifier")? .context("Could not load application identifier")?
.ident(); .ident();
let mut pin = None; let mut pin = self.pin_cache.get(&fp).cloned();
while transaction while transaction
.pw_status_bytes() .pw_status_bytes()
.map_err(Error::PwStatusBytes)? .map_err(Error::PwStatusBytes)?
.err_count_pw1() .err_count_pw1()
> 0 > 0
&& pin.is_none()
{ {
transaction.reload_ard()?; transaction.reload_ard()?;
let attempts = transaction let attempts = transaction
@ -236,12 +239,11 @@ impl DecryptionHelper for &mut SmartcardManager {
format!("Unlock card {card_id} ({cardholder_name})\n{rpea}: {attempts}\n\nPIN: ") format!("Unlock card {card_id} ({cardholder_name})\n{rpea}: {attempts}\n\nPIN: ")
}; };
let temp_pin = self.pm.prompt_passphrase(&message)?; let temp_pin = self.pm.prompt_passphrase(&message)?;
let verification_status = let verification_status = transaction.verify_user_pin(temp_pin.as_str().trim());
transaction.verify_user_pin(temp_pin.as_str().trim());
match verification_status { match verification_status {
Ok(_) => { Ok(_) => {
self.pin_cache.insert(fp.clone(), temp_pin.clone());
pin.replace(temp_pin); pin.replace(temp_pin);
break;
} }
Err(CardError::CardStatus(StatusBytes::IncorrectParametersCommandDataField)) => { Err(CardError::CardStatus(StatusBytes::IncorrectParametersCommandDataField)) => {
self.pm.prompt_message("Invalid PIN length entered.")?; self.pm.prompt_message("Invalid PIN length entered.")?;