diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index 02a0b12..97f4dac 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -31,10 +31,15 @@ fn main() -> Result<(), Box> { // Ident of the OpenPGP Card that will be used for tests. let test_card_ident = env::var("TEST_CARD_IDENT"); + // "serial" for opening a specific card through scdaemon + let test_card_serial = env::var("TEST_CARD_SERIAL")?; + if let Ok(test_card_ident) = test_card_ident { println!("** get card"); // let mut oc = CardBase::open_by_ident(&test_card_ident)?; - let mut oc = ScdClient::open_scdc(SOCKET)?; + // let mut oc = ScdClient::open_scdc(SOCKET)?; + let mut oc = + ScdClient::open_scdc_by_serial(SOCKET, &test_card_serial)?; // card metadata diff --git a/scdc/src/lib.rs b/scdc/src/lib.rs index d081b14..a8119ee 100644 --- a/scdc/src/lib.rs +++ b/scdc/src/lib.rs @@ -30,11 +30,51 @@ impl ScdClient { CardBase::open_card(card_client_box) } + /// Create a CardBase object that uses an scdaemon instance as its + /// backend, asking for a specific card by `serial`. + pub fn open_scdc_by_serial( + socket: &str, + serial: &str, + ) -> Result { + let mut card_client = ScdClient::new(socket)?; + + card_client.select_card(serial)?; + + let card_client_box = Box::new(card_client) as CardClientBox; + + CardBase::open_card(card_client_box) + } + pub fn new(socket: &str) -> Result { let client = RT.lock().unwrap().block_on(Client::connect(socket))?; let client = Arc::new(Mutex::new(client)); Ok(Self { client }) } + + /// SERIALNO --demand=D27600012401030400050000A8350000 + fn select_card(&mut self, serial: &str) -> Result<()> { + let mut client = self.client.lock().unwrap(); + + let send = format!("SERIALNO --demand={}\n", serial); + client.send(send)?; + + let mut rt = RT.lock().unwrap(); + + while let Some(response) = rt.block_on(client.next()) { + if let Err(_) = response { + return Err(anyhow!("Card not found")); + } + + if let Ok(Response::Status { .. }) = response { + // drop remaining lines + while let Some(drop) = rt.block_on(client.next()) {} + + return Ok(()); + } + } + + Err(anyhow!("Card not found")) + } } impl CardClient for ScdClient {