diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index cea025c..db91bc0 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -24,12 +24,12 @@ const TEST_ENC_MSG: &str = "example/encrypted_to_25519.asc"; fn main() -> Result<(), Box> { env_logger::init(); - // Serial number of the OpenPGP Card that will be used for tests. - let test_card_serial = env::var("TEST_CARD_SERIAL"); + // Ident of the OpenPGP Card that will be used for tests. + let test_card_ident = env::var("TEST_CARD_IDENT"); - if let Ok(test_card_serial) = test_card_serial { + if let Ok(test_card_ident) = test_card_ident { println!("** get card"); - let oc = CardBase::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_ident(&test_card_ident)?; // card metadata @@ -37,7 +37,7 @@ fn main() -> Result<(), Box> { let app_id = oc.get_aid()?; println!("app id: {:x?}\n\n", app_id); - println!(" serial: {:?}\n\n", app_id.serial()); + println!(" ident: {:?}\n\n", app_id.ident()); let eli = oc.get_extended_length_information()?; println!("extended_length_info: {:?}\n\n", eli); @@ -75,7 +75,7 @@ fn main() -> Result<(), Box> { // CAUTION: Write commands ahead! // Try not to overwrite your production cards. // --------------------------------------------- - assert_eq!(app_id.serial(), test_card_serial); + assert_eq!(app_id.ident(), test_card_ident); oc.factory_reset()?; @@ -127,11 +127,11 @@ fn main() -> Result<(), Box> { // Open fresh Card for decrypt // ----------------------------- - let oc = CardBase::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_ident(&test_card_ident)?; let app_id = oc.get_aid()?; // Check that we're still using the expected card - assert_eq!(app_id.serial(), test_card_serial); + assert_eq!(app_id.ident(), test_card_ident); match oc.verify_pw1("123456") { Ok(oc_user) => { @@ -160,7 +160,7 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for signing // ----------------------------- - let oc = CardBase::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_ident(&test_card_ident)?; // Sign match oc.verify_pw1_for_signing("123456") { @@ -185,7 +185,7 @@ fn main() -> Result<(), Box> { _ => panic!("verify pw1 failed"), } } else { - println!("Please set environment variable TEST_CARD_SERIAL."); + println!("Please set environment variable TEST_CARD_IDENT."); println!(); println!("NOTE: the configured card will get overwritten!"); @@ -196,7 +196,7 @@ fn main() -> Result<(), Box> { let cards = openpgp_card::CardBase::list_cards()?; for c in cards { - println!(" '{}'", c.get_aid()?.serial()); + println!(" '{}'", c.get_aid()?.ident()); } } diff --git a/openpgp-card/src/errors.rs b/openpgp-card/src/errors.rs index 7fbf720..61b7ff4 100644 --- a/openpgp-card/src/errors.rs +++ b/openpgp-card/src/errors.rs @@ -145,8 +145,8 @@ pub enum SmartcardError { #[error("No reader found.")] NoReaderFoundError, - #[error("The requested card was not found.")] - CardNotFound, + #[error("The requested card '{0}' was not found.")] + CardNotFound(String), #[error("Failed to connect to the card: {0}")] SmartCardConnectionError(String), diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 874702d..175c4fe 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -233,8 +233,11 @@ impl CardBase { Ok(ocs) } - /// Find an OpenPGP card by serial number, open and return it. - pub fn open_by_serial(serial: &str) -> Result { + /// Find an OpenPGP card by "ident", open and return it. + /// + /// The ident is constructed as a concatenation of manufacturer + /// id, a colon, and the card serial. Example: "1234:5678ABCD". + pub fn open_by_ident(ident: &str) -> Result { let cards = card::get_cards().map_err(|e| { OpenpgpCardError::Smartcard(SmartcardError::Error(format!( "{:?}", @@ -247,14 +250,16 @@ impl CardBase { if let Ok(opened_card) = res { let res = opened_card.get_aid(); if let Ok(aid) = res { - if aid.serial() == serial { + if aid.ident() == ident { return Ok(opened_card); } } } } - Err(OpenpgpCardError::Smartcard(SmartcardError::CardNotFound)) + Err(OpenpgpCardError::Smartcard(SmartcardError::CardNotFound( + ident.to_string(), + ))) } /// Open connection to some card and select the openpgp applet diff --git a/openpgp-card/src/parse/application_id.rs b/openpgp-card/src/parse/application_id.rs index 38e8226..359fc9b 100644 --- a/openpgp-card/src/parse/application_id.rs +++ b/openpgp-card/src/parse/application_id.rs @@ -55,7 +55,22 @@ impl TryFrom<&[u8]> for ApplicationId { } impl ApplicationId { - pub fn serial(&self) -> String { - format!("{:08X}", self.serial) + pub fn serial(&self) -> u32 { + self.serial + } + + pub fn manufacturer(&self) -> u16 { + self.manufacturer + } + + /// This ident is constructed as the concatenation of manufacturer + /// id, a colon, and the card serial (in hexadecimal representation). + /// + /// It is a more easily human-readable, shorter form of the full + /// 16-byte AID ("Application Identifier"). + /// + /// Example: "1234:5678ABCD". + pub fn ident(&self) -> String { + format!("{:04X}:{:08X}", self.manufacturer, self.serial) } }