#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeySlot {
Signature,
Encryption,
Authentication,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TouchMode {
Off,
On,
Fixed,
Cached,
CachedFixed,
}
#[derive(Debug, Clone)]
pub struct CardSummary {
pub ident: String,
pub manufacturer_name: String,
pub serial_number: String,
pub cardholder_name: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct CardInfo {
pub ident: String,
pub serial_number: String,
pub cardholder_name: Option<String>,
pub public_key_url: Option<String>,
pub signature_fingerprint: Option<String>,
pub encryption_fingerprint: Option<String>,
pub authentication_fingerprint: Option<String>,
pub signature_counter: u32,
pub pin_retry_counter: u8,
pub reset_code_retry_counter: u8,
pub admin_pin_retry_counter: u8,
pub manufacturer: Option<String>,
pub manufacturer_name: Option<String>,
}
#[derive(Debug, Clone)]
pub struct SlotMatch {
pub slot: KeySlot,
pub fingerprint: String,
}
#[derive(Debug, Clone)]
pub struct CardKeyMatch {
pub card: CardInfo,
pub matching_slots: Vec<SlotMatch>,
}
#[derive(Debug, Clone)]
pub enum CardError {
NotConnected,
SelectFailed,
PinBlocked,
PinIncorrect {
retries_remaining: u8,
},
AdminPinRequired,
KeyNotPresent(KeySlot),
UnsupportedAlgorithm(String),
CommunicationError(String),
InvalidData(String),
Timeout,
CardError(String),
}
impl std::fmt::Display for CardError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CardError::NotConnected => write!(f, "No smart card connected"),
CardError::SelectFailed => write!(f, "Failed to select OpenPGP applet"),
CardError::PinBlocked => write!(f, "PIN is blocked"),
CardError::PinIncorrect { retries_remaining } => {
write!(f, "PIN incorrect, {} retries remaining", retries_remaining)
}
CardError::AdminPinRequired => write!(f, "Admin PIN required"),
CardError::KeyNotPresent(slot) => write!(f, "Key not present in slot {:?}", slot),
CardError::UnsupportedAlgorithm(algo) => {
write!(f, "Algorithm not supported: {}", algo)
}
CardError::CommunicationError(msg) => write!(f, "Communication error: {}", msg),
CardError::InvalidData(msg) => write!(f, "Invalid data: {}", msg),
CardError::Timeout => write!(f, "Operation timed out"),
CardError::CardError(msg) => write!(f, "Card error: {}", msg),
}
}
}
impl std::error::Error for CardError {}
#[cfg(feature = "card")]
impl From<openpgp_card::Error> for CardError {
fn from(err: openpgp_card::Error) -> Self {
let msg = format!("{}", err);
if msg.contains("6983") || msg.contains("blocked") {
CardError::PinBlocked
} else if msg.contains("63C") {
CardError::PinIncorrect {
retries_remaining: 3,
}
} else {
CardError::CardError(msg)
}
}
}