use card_backend_pcsc::PcscBackend;
pub fn set_pin() -> Result<(), Box<dyn std::error::Error>> {
for card in PcscBackend::cards(None)? {
let card = card?;
let mut card = openpgp_card::Card::new(card)?;
let mut tx = card.transaction()?;
let ident = tx.application_identifier()?.ident();
println!("Found OpenPGP card {}", ident);
if let Ok(Some(pin)) = openpgp_card_state::get_pin(&ident) {
if tx
.card()
.verify_pw1_sign(pin.as_bytes().to_vec().into())
.is_err()
{
openpgp_card_state::drop_pin(&ident)?;
println!(" An invalid User PIN has been dropped from openpgp-card-state");
if let Err(e) = get_and_store_pin(&mut tx, &ident) {
eprintln!(" Failed to set a new User PIN for the card: {}", e);
}
} else {
println!(" A valid User PIN is available via openpgp-card-state");
}
} else {
println!(" No User PIN is stored in openpgp-card-state");
if let Err(e) = get_and_store_pin(&mut tx, &ident) {
eprintln!(" Failed to store a new User PIN: {}", e);
}
}
println!();
}
Ok(())
}
fn get_and_store_pin(
tx: &mut openpgp_card::Card<openpgp_card::state::Transaction<'_>>,
ident: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let pin = rpassword::prompt_password(" Enter User PIN to store (or <Enter> to skip): ")?;
if !pin.is_empty() {
tx.card().verify_pw1_sign(pin.as_bytes().to_vec().into())?;
openpgp_card_state::set_pin(ident, &pin, None)?;
println!(" User PIN has been stored in openpgp-card-state");
} else {
println!(" Skipped");
}
Ok(())
}