diff --git a/card-functionality/src/tests.rs b/card-functionality/src/tests.rs index d055278..7c89d21 100644 --- a/card-functionality/src/tests.rs +++ b/card-functionality/src/tests.rs @@ -1,19 +1,19 @@ // SPDX-FileCopyrightText: 2021 Heiko Schaefer // SPDX-License-Identifier: MIT OR Apache-2.0 -use anyhow::{Error, Result}; +use anyhow::Result; use std::str::FromStr; use std::string::FromUtf8Error; -use thiserror::Error; +use thiserror; use sequoia_openpgp::parse::Parse; use sequoia_openpgp::serialize::SerializeInto; use sequoia_openpgp::Cert; +use openpgp_card; use openpgp_card::algorithm::AlgoSimple; use openpgp_card::card_do::{KeyGenerationTime, Sex}; -use openpgp_card::errors::{OcErrorStatus, OpenpgpCardError}; -use openpgp_card::{CardApp, KeyType}; +use openpgp_card::{CardApp, Error, KeyType, StatusByte}; use openpgp_card_sequoia::{ make_cert, public_key_material_to_key, public_to_fingerprint, }; @@ -23,23 +23,23 @@ use crate::util; #[derive(Debug)] pub enum TestResult { - Status(OcErrorStatus), + Status(StatusByte), StatusOk, Text(String), } type TestOutput = Vec; -#[derive(Error, Debug)] +#[derive(thiserror::Error, Debug)] pub enum TestError { #[error("Failed to upload key {0} ({1})")] - KeyUploadError(String, Error), + KeyUploadError(String, anyhow::Error), #[error(transparent)] - OPGP(#[from] OpenpgpCardError), + OPGP(#[from] Error), #[error(transparent)] - OCard(#[from] OcErrorStatus), + OCard(#[from] StatusByte), #[error(transparent)] Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error @@ -485,8 +485,8 @@ pub fn test_verify( // try to set name without verify, assert result is not ok! let res = ca.set_name("Notverified< { + Err(Error::CardStatus(s)) => { // e.g. yubikey5 returns an error status! out.push(TestResult::Status(s)); } @@ -512,7 +512,7 @@ pub fn test_verify( ca.verify_pw1("123456")?; match ca.check_pw3() { - Err(OpenpgpCardError::OcStatus(s)) => { + Err(Error::CardStatus(s)) => { // e.g. yubikey5 returns an error status! out.push(TestResult::Status(s)); } diff --git a/openpgp-card-sequoia/src/decryptor.rs b/openpgp-card-sequoia/src/decryptor.rs index 2f7838f..ccc5693 100644 --- a/openpgp-card-sequoia/src/decryptor.rs +++ b/openpgp-card-sequoia/src/decryptor.rs @@ -16,8 +16,7 @@ use openpgp::Cert; use sequoia_openpgp as openpgp; use openpgp_card::crypto_data::Cryptogram; -use openpgp_card::errors::OpenpgpCardError; -use openpgp_card::CardApp; +use openpgp_card::{CardApp, Error}; use crate::PublicKey; @@ -38,7 +37,7 @@ impl<'a> CardDecryptor<'a> { ca: &'a mut CardApp, cert: &Cert, policy: &dyn Policy, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { // Get the fingerprint for the decryption key from the card. let ard = ca.get_app_data()?; let fps = ard.get_fingerprints()?; @@ -63,12 +62,12 @@ impl<'a> CardDecryptor<'a> { let public = keys[0].clone(); Ok(Self { ca, public }) } else { - Err(OpenpgpCardError::InternalError(anyhow!( + Err(Error::InternalError(anyhow!( "Failed to find a matching (sub)key in cert" ))) } } else { - Err(OpenpgpCardError::InternalError(anyhow!( + Err(Error::InternalError(anyhow!( "Failed to get the decryption key's Fingerprint from the card" ))) } diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index a13f239..1364dd2 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -7,7 +7,6 @@ use anyhow::{anyhow, Context, Result}; use std::convert::TryFrom; use std::convert::TryInto; -use std::error::Error; use std::io; use std::ops::{Deref, DerefMut}; use std::time::SystemTime; @@ -41,9 +40,7 @@ use openpgp_card::crypto_data::{ CardUploadableKey, Cryptogram, EccKey, EccType, Hash, PrivateKeyMaterial, PublicKeyMaterial, RSAKey, }; -use openpgp_card::{ - errors::OpenpgpCardError, CardApp, CardClientBox, KeyType, Response, -}; +use openpgp_card::{CardApp, CardClientBox, Error, KeyType, Response}; use crate::signer::CardSigner; @@ -373,7 +370,7 @@ impl CardUploadableKey for SequoiaKey { ts.into() } - fn get_fp(&self) -> Result { + fn get_fp(&self) -> Result { let fp = self.key.fingerprint(); fp.as_bytes().try_into() } @@ -455,7 +452,7 @@ pub fn upload_from_cert_yolo( cert: &openpgp::Cert, key_type: KeyType, password: Option, -) -> Result<(), Box> { +) -> Result<(), Box> { let policy = StandardPolicy::new(); // Find all suitable (sub)keys for key_type. @@ -488,7 +485,7 @@ pub fn upload_key( vka: ValidErasedKeyAmalgamation, key_type: KeyType, password: Option, -) -> Result<(), OpenpgpCardError> { +) -> Result<(), Error> { let sqk = SequoiaKey::new(vka, password); oca.upload_key(Box::new(sqk), key_type) @@ -546,7 +543,7 @@ pub fn public_to_fingerprint( pkm: &PublicKeyMaterial, time: KeyGenerationTime, kt: KeyType, -) -> Result { +) -> Result { // Transform PublicKeyMaterial into a Sequoia Key let key = public_key_material_to_key(pkm, kt, time)?; @@ -581,7 +578,7 @@ impl CardBase { /// Set up connection (cache "application related data") to a /// CardClient, on which the openpgp applet has already been opened. - pub fn open_card(ccb: CardClientBox) -> Result { + pub fn open_card(ccb: CardClientBox) -> Result { // read and cache "application related data" let mut card_app = CardApp::from(ccb); @@ -602,13 +599,11 @@ impl CardBase { self.card_app.get_app_data() } - pub fn get_application_id( - &self, - ) -> Result { + pub fn get_application_id(&self) -> Result { self.ard.get_application_id() } - pub fn get_historical(&self) -> Result { + pub fn get_historical(&self) -> Result { self.ard.get_historical() } @@ -626,9 +621,7 @@ impl CardBase { unimplemented!() } - pub fn get_extended_capabilities( - &self, - ) -> Result { + pub fn get_extended_capabilities(&self) -> Result { self.ard.get_extended_capabilities() } @@ -641,9 +634,7 @@ impl CardBase { self.ard.get_pw_status_bytes() } - pub fn get_fingerprints( - &self, - ) -> Result, OpenpgpCardError> { + pub fn get_fingerprints(&self) -> Result, Error> { self.ard.get_fingerprints() } @@ -730,7 +721,7 @@ impl CardBase { } } - pub fn check_pw1(&mut self) -> Result { + pub fn check_pw1(&mut self) -> Result { self.card_app.check_pw1() } @@ -744,7 +735,7 @@ impl CardBase { } } - pub fn check_pw3(&mut self) -> Result { + pub fn check_pw3(&mut self) -> Result { self.card_app.check_pw3() } @@ -783,10 +774,7 @@ impl DerefMut for CardUser { impl CardUser { /// Decrypt the ciphertext in `dm`, on the card. - pub fn decrypt( - &mut self, - dm: Cryptogram, - ) -> Result, OpenpgpCardError> { + pub fn decrypt(&mut self, dm: Cryptogram) -> Result, Error> { self.card_app.decrypt(dm) } } @@ -820,7 +808,7 @@ impl CardSign { pub fn signature_for_hash( &mut self, hash: Hash, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { self.card_app.signature_for_hash(hash) } } @@ -847,10 +835,7 @@ impl DerefMut for CardAdmin { } impl CardAdmin { - pub fn set_name( - &mut self, - name: &str, - ) -> Result { + pub fn set_name(&mut self, name: &str) -> Result { if name.len() >= 40 { return Err(anyhow!("name too long").into()); } @@ -863,10 +848,7 @@ impl CardAdmin { self.card_app.set_name(name) } - pub fn set_lang( - &mut self, - lang: &str, - ) -> Result { + pub fn set_lang(&mut self, lang: &str) -> Result { if lang.len() > 8 { return Err(anyhow!("lang too long").into()); } @@ -874,14 +856,11 @@ impl CardAdmin { self.card_app.set_lang(lang) } - pub fn set_sex(&mut self, sex: Sex) -> Result { + pub fn set_sex(&mut self, sex: Sex) -> Result { self.card_app.set_sex(sex) } - pub fn set_url( - &mut self, - url: &str, - ) -> Result { + pub fn set_url(&mut self, url: &str) -> Result { if url.chars().any(|c| !c.is_ascii()) { return Err(anyhow!("Invalid char in url").into()); } @@ -900,7 +879,7 @@ impl CardAdmin { &mut self, key: Box, key_type: KeyType, - ) -> Result<(), OpenpgpCardError> { + ) -> Result<(), Error> { self.card_app.key_import(key, key_type) } } diff --git a/openpgp-card-sequoia/src/signer.rs b/openpgp-card-sequoia/src/signer.rs index 6661e0b..6e249f3 100644 --- a/openpgp-card-sequoia/src/signer.rs +++ b/openpgp-card-sequoia/src/signer.rs @@ -11,8 +11,7 @@ use openpgp::types::{Curve, PublicKeyAlgorithm}; use sequoia_openpgp as openpgp; use openpgp_card::crypto_data::Hash; -use openpgp_card::errors::OpenpgpCardError; -use openpgp_card::CardApp; +use openpgp_card::{CardApp, Error}; use crate::PublicKey; @@ -33,7 +32,7 @@ impl<'a> CardSigner<'a> { ca: &'a mut CardApp, cert: &openpgp::Cert, policy: &dyn Policy, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { // Get the fingerprint for the signing key from the card. let ard = ca.get_app_data()?; let fps = ard.get_fingerprints()?; @@ -60,12 +59,12 @@ impl<'a> CardSigner<'a> { Ok(Self::with_pubkey(ca, public)) } else { - Err(OpenpgpCardError::InternalError(anyhow!( + Err(Error::InternalError(anyhow!( "Failed to find a matching (sub)key in cert" ))) } } else { - Err(OpenpgpCardError::InternalError(anyhow!( + Err(Error::InternalError(anyhow!( "Failed to get the signing key's Fingerprint \ from the card" ))) diff --git a/openpgp-card/src/apdu/mod.rs b/openpgp-card/src/apdu/mod.rs index 172feb9..57718e8 100644 --- a/openpgp-card/src/apdu/mod.rs +++ b/openpgp-card/src/apdu/mod.rs @@ -11,10 +11,8 @@ pub mod response; use anyhow::Result; use std::convert::TryFrom; -use crate::apdu::command::Command; -use crate::apdu::response::RawResponse; -use crate::errors::{OcErrorStatus, OpenpgpCardError}; -use crate::CardClientBox; +use crate::apdu::{command::Command, response::RawResponse}; +use crate::{CardClientBox, Error, StatusByte}; // "Maximum amount of bytes in a short APDU command or response" (from pcsc) const MAX_BUFFER_SIZE: usize = 264; @@ -34,7 +32,7 @@ pub(crate) fn send_command( card_client: &mut CardClientBox, cmd: Command, expect_reply: bool, -) -> Result { +) -> Result { let mut resp = RawResponse::try_from(send_command_low_level( card_client, cmd, @@ -75,7 +73,7 @@ fn send_command_low_level( card_client: &mut CardClientBox, cmd: Command, expect_reply: bool, -) -> Result, OpenpgpCardError> { +) -> Result, Error> { let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) = if let Some(caps) = card_client.get_caps() { log::debug!("found card caps data!"); @@ -151,9 +149,8 @@ fn send_command_low_level( d.to_vec(), ); - let serialized = partial - .serialize(ext) - .map_err(OpenpgpCardError::InternalError)?; + let serialized = + partial.serialize(ext).map_err(Error::InternalError)?; log::debug!(" -> chunked APDU command: {:x?}", &serialized); @@ -162,7 +159,7 @@ fn send_command_low_level( log::debug!(" <- APDU chunk response: {:x?}", &resp); if resp.len() < 2 { - return Err(OpenpgpCardError::ResponseLength(resp.len())); + return Err(Error::ResponseLength(resp.len())); } if !last { @@ -176,7 +173,7 @@ fn send_command_low_level( || (sw1 == 0x68 && sw2 == 0x83)) { // Unexpected status for a non-final chunked response - return Err(OcErrorStatus::from((sw1, sw2)).into()); + return Err(StatusByte::from((sw1, sw2)).into()); } // ISO: "If SW1-SW2 is set to '6884', then command @@ -193,7 +190,7 @@ fn send_command_low_level( // Can't send this command to the card, because it is too long and // the card doesn't support command chaining. if serialized.len() > max_cmd_bytes { - return Err(OpenpgpCardError::CommandTooLong(serialized.len())); + return Err(Error::CommandTooLong(serialized.len())); } log::debug!(" -> APDU command: {:x?}", &serialized); diff --git a/openpgp-card/src/apdu/response.rs b/openpgp-card/src/apdu/response.rs index 714dead..15852b0 100644 --- a/openpgp-card/src/apdu/response.rs +++ b/openpgp-card/src/apdu/response.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2021 Heiko Schaefer // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::errors::{OcErrorStatus, OpenpgpCardError}; +use crate::{Error, StatusByte}; use std::convert::TryFrom; /// Response from the card to a command. @@ -35,29 +35,27 @@ pub(crate) struct RawResponse { } impl TryFrom for Response { - type Error = OpenpgpCardError; + type Error = Error; fn try_from(value: RawResponse) -> Result { if value.is_ok() { Ok(Response { data: value.data }) } else { - Err(OpenpgpCardError::OcStatus(OcErrorStatus::from( - value.status(), - ))) + Err(Error::CardStatus(StatusByte::from(value.status()))) } } } impl RawResponse { - pub fn check_ok(&self) -> Result<(), OcErrorStatus> { + pub fn check_ok(&self) -> Result<(), StatusByte> { if !self.is_ok() { - Err(OcErrorStatus::from((self.sw1, self.sw2))) + Err(StatusByte::from((self.sw1, self.sw2))) } else { Ok(()) } } - pub fn data(&self) -> Result<&[u8], OcErrorStatus> { + pub fn data(&self) -> Result<&[u8], StatusByte> { self.check_ok()?; Ok(&self.data) } @@ -87,15 +85,15 @@ impl RawResponse { } impl TryFrom> for RawResponse { - type Error = OpenpgpCardError; + type Error = Error; fn try_from(mut data: Vec) -> Result { let sw2 = data .pop() - .ok_or_else(|| OpenpgpCardError::ResponseLength(data.len()))?; + .ok_or_else(|| Error::ResponseLength(data.len()))?; let sw1 = data .pop() - .ok_or_else(|| OpenpgpCardError::ResponseLength(data.len()))?; + .ok_or_else(|| Error::ResponseLength(data.len()))?; Ok(RawResponse { data, sw1, sw2 }) } diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 1dd8dcb..c99c213 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -18,8 +18,8 @@ use crate::card_do::{ use crate::crypto_data::{ CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial, }; -use crate::errors::OpenpgpCardError; use crate::tlv::{tag::Tag, value::Value, Tlv}; +use crate::Error; use crate::{apdu, keys, CardCaps, CardClientBox, KeyType}; /// Low-level access to OpenPGP card functionality. @@ -92,7 +92,7 @@ impl CardApp { // --- select --- /// Select the OpenPGP card application - pub fn select(&mut self) -> Result { + pub fn select(&mut self) -> Result { let select_openpgp = commands::select_openpgp(); apdu::send_command(&mut self.card_client, select_openpgp, false)? .try_into() @@ -207,9 +207,7 @@ impl CardApp { /// /// Call select_data() before calling this fn, to select a particular /// certificate (if the card supports multiple certificates). - pub fn get_cardholder_certificate( - &mut self, - ) -> Result { + pub fn get_cardholder_certificate(&mut self) -> Result { let cmd = commands::get_cardholder_certificate(); apdu::send_command(&mut self.card_client, cmd, true)?.try_into() } @@ -233,7 +231,7 @@ impl CardApp { &mut self, num: u8, tag: &[u8], - ) -> Result { + ) -> Result { let tlv = Tlv::new( [0x60], Value::C(vec![Tlv::new([0x5c], Value::S(tag.to_vec()))]), @@ -308,7 +306,7 @@ impl CardApp { pub fn verify_pw1_for_signing( &mut self, pin: &str, - ) -> Result { + ) -> Result { assert!(pin.len() >= 6); // FIXME: Err let verify = commands::verify_pw1_81(pin.as_bytes().to_vec()); @@ -321,19 +319,14 @@ impl CardApp { /// /// (Note: some cards don't correctly implement this feature, /// e.g. yubikey 5) - pub fn check_pw1_for_signing( - &mut self, - ) -> Result { + pub fn check_pw1_for_signing(&mut self) -> Result { let verify = commands::verify_pw1_81(vec![]); apdu::send_command(&mut self.card_client, verify, false)?.try_into() } /// Verify PW1 (user) and set an appropriate access status. /// (For operations except signing, mode 82). - pub fn verify_pw1( - &mut self, - pin: &str, - ) -> Result { + pub fn verify_pw1(&mut self, pin: &str) -> Result { assert!(pin.len() >= 6); // FIXME: Err let verify = commands::verify_pw1_82(pin.as_bytes().to_vec()); @@ -347,16 +340,13 @@ impl CardApp { /// /// (Note: some cards don't correctly implement this feature, /// e.g. yubikey 5) - pub fn check_pw1(&mut self) -> Result { + pub fn check_pw1(&mut self) -> Result { let verify = commands::verify_pw1_82(vec![]); apdu::send_command(&mut self.card_client, verify, false)?.try_into() } /// Verify PW3 (admin) and set an appropriate access status. - pub fn verify_pw3( - &mut self, - pin: &str, - ) -> Result { + pub fn verify_pw3(&mut self, pin: &str) -> Result { assert!(pin.len() >= 8); // FIXME: Err let verify = commands::verify_pw3(pin.as_bytes().to_vec()); @@ -369,7 +359,7 @@ impl CardApp { /// /// (Note: some cards don't correctly implement this feature, /// e.g. yubikey 5) - pub fn check_pw3(&mut self) -> Result { + pub fn check_pw3(&mut self) -> Result { let verify = commands::verify_pw3(vec![]); apdu::send_command(&mut self.card_client, verify, false)?.try_into() } @@ -380,10 +370,7 @@ impl CardApp { /// /// (This is a convenience wrapper around the low-level pso_decipher /// operation, it builds the required `data` field from `dm`) - pub fn decrypt( - &mut self, - dm: Cryptogram, - ) -> Result, OpenpgpCardError> { + pub fn decrypt(&mut self, dm: Cryptogram) -> Result, Error> { match dm { Cryptogram::RSA(message) => { let mut data = vec![0x0]; @@ -409,10 +396,7 @@ impl CardApp { /// Run decryption operation on the smartcard (low level operation) /// (7.2.11 PSO: DECIPHER) - fn pso_decipher( - &mut self, - data: Vec, - ) -> Result, OpenpgpCardError> { + fn pso_decipher(&mut self, data: Vec) -> Result, Error> { // The OpenPGP card is already connected and PW1 82 has been verified let dec_cmd = commands::decryption(data); let resp = apdu::send_command(&mut self.card_client, dec_cmd, true)?; @@ -431,7 +415,7 @@ impl CardApp { pub fn signature_for_hash( &mut self, hash: Hash, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { let data = match hash { Hash::SHA256(_) | Hash::SHA384(_) | Hash::SHA512(_) => { let tlv = Tlv::new( @@ -466,7 +450,7 @@ impl CardApp { fn pso_compute_digital_signature( &mut self, data: Vec, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { let dec_cmd = commands::signature(data); let resp = apdu::send_command(&mut self.card_client, dec_cmd, true)?; @@ -492,33 +476,24 @@ impl CardApp { Ok(resp.data()?.to_vec()) } - pub fn set_name( - &mut self, - name: &str, - ) -> Result { + pub fn set_name(&mut self, name: &str) -> Result { let put_name = commands::put_name(name.as_bytes().to_vec()); apdu::send_command(&mut self.card_client, put_name, false)?.try_into() } - pub fn set_lang( - &mut self, - lang: &str, - ) -> Result { + pub fn set_lang(&mut self, lang: &str) -> Result { let put_lang = commands::put_lang(lang.as_bytes().to_vec()); apdu::send_command(self.card_client.borrow_mut(), put_lang, false)? .try_into() } - pub fn set_sex(&mut self, sex: Sex) -> Result { + pub fn set_sex(&mut self, sex: Sex) -> Result { let put_sex = commands::put_sex((&sex).into()); apdu::send_command(self.card_client.borrow_mut(), put_sex, false)? .try_into() } - pub fn set_url( - &mut self, - url: &str, - ) -> Result { + pub fn set_url(&mut self, url: &str) -> Result { let put_url = commands::put_url(url.as_bytes().to_vec()); apdu::send_command(&mut self.card_client, put_url, false)?.try_into() } @@ -527,7 +502,7 @@ impl CardApp { &mut self, time: KeyGenerationTime, key_type: KeyType, - ) -> Result { + ) -> Result { // Timestamp update let time_value: Vec = time .get() @@ -549,7 +524,7 @@ impl CardApp { &mut self, fp: Fingerprint, key_type: KeyType, - ) -> Result { + ) -> Result { let fp_cmd = commands::put_data( &[key_type.get_fingerprint_put_tag()], fp.as_bytes().to_vec(), @@ -573,7 +548,7 @@ impl CardApp { &mut self, pw_status: &PWStatus, long: bool, - ) -> Result { + ) -> Result { let data = pw_status.serialize_for_put(long); let cmd = commands::put_pw_status(data); @@ -587,7 +562,7 @@ impl CardApp { pub fn set_cardholder_certificate( &mut self, data: Vec, - ) -> Result { + ) -> Result { let cmd = commands::put_cardholder_certificate(data); apdu::send_command(&mut self.card_client, cmd, false)?.try_into() } @@ -598,7 +573,7 @@ impl CardApp { &mut self, key_type: KeyType, algo: &Algo, - ) -> Result { + ) -> Result { // FIXME: caching? let ard = self.get_app_data()?; @@ -668,7 +643,7 @@ impl CardApp { &mut self, key: Box, key_type: KeyType, - ) -> Result<(), OpenpgpCardError> { + ) -> Result<(), Error> { let algo_list = self.get_algo_info(); // An error is ok - it's fine if a card doesn't offer a list of @@ -689,10 +664,10 @@ impl CardApp { &PublicKeyMaterial, KeyGenerationTime, KeyType, - ) -> Result, + ) -> Result, key_type: KeyType, algo: Option<&Algo>, - ) -> Result<(PublicKeyMaterial, KeyGenerationTime), OpenpgpCardError> { + ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> { keys::gen_key_with_metadata(self, fp_from_pub, key_type, algo) } @@ -707,10 +682,10 @@ impl CardApp { &PublicKeyMaterial, KeyGenerationTime, KeyType, - ) -> Result, + ) -> Result, key_type: KeyType, algo: AlgoSimple, - ) -> Result<(PublicKeyMaterial, KeyGenerationTime), OpenpgpCardError> { + ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> { let algo = algo.get_algo(key_type); self.generate_key(fp_from_pub, key_type, Some(&algo)) } @@ -724,7 +699,7 @@ impl CardApp { pub fn get_pub_key( &mut self, key_type: KeyType, - ) -> Result { + ) -> Result { keys::get_pub_key(self, key_type) } } diff --git a/openpgp-card/src/card_do/extended_cap.rs b/openpgp-card/src/card_do/extended_cap.rs index f9f05ed..e325910 100644 --- a/openpgp-card/src/card_do/extended_cap.rs +++ b/openpgp-card/src/card_do/extended_cap.rs @@ -8,9 +8,8 @@ use nom::{combinator, number::complete as number, sequence}; use std::collections::HashSet; use std::convert::TryFrom; -use crate::card_do::complete; -use crate::card_do::{ExtendedCap, Features}; -use crate::errors::OpenpgpCardError; +use crate::card_do::{complete, ExtendedCap, Features}; +use crate::Error; fn features(input: &[u8]) -> nom::IResult<&[u8], HashSet> { combinator::map(number::u8, |b| { @@ -70,7 +69,7 @@ impl ExtendedCap { } impl TryFrom<&[u8]> for ExtendedCap { - type Error = OpenpgpCardError; + type Error = Error; fn try_from(input: &[u8]) -> Result { let ec = complete(parse(input))?; diff --git a/openpgp-card/src/card_do/fingerprint.rs b/openpgp-card/src/card_do/fingerprint.rs index 5628439..a010c82 100644 --- a/openpgp-card/src/card_do/fingerprint.rs +++ b/openpgp-card/src/card_do/fingerprint.rs @@ -10,7 +10,7 @@ use std::convert::TryInto; use std::fmt; use crate::card_do::{Fingerprint, KeySet}; -use crate::errors::OpenpgpCardError; +use crate::Error; impl From<[u8; 20]> for Fingerprint { fn from(data: [u8; 20]) -> Self { @@ -19,7 +19,7 @@ impl From<[u8; 20]> for Fingerprint { } impl TryFrom<&[u8]> for Fingerprint { - type Error = OpenpgpCardError; + type Error = Error; fn try_from(input: &[u8]) -> Result { log::trace!( @@ -84,9 +84,7 @@ fn fingerprints(input: &[u8]) -> nom::IResult<&[u8], KeySet> { } /// Parse three fingerprints from the card into a KeySet of Fingerprints -pub(crate) fn to_keyset( - input: &[u8], -) -> Result, OpenpgpCardError> { +pub(crate) fn to_keyset(input: &[u8]) -> Result, Error> { log::trace!("Fingerprint from input: {:x?}, len {}", input, input.len()); // The input may be longer than 3 fingerprint, don't fail if it hasn't @@ -94,5 +92,5 @@ pub(crate) fn to_keyset( self::fingerprints(input) .map(|res| res.1) .map_err(|err| anyhow!("Parsing failed: {:?}", err)) - .map_err(OpenpgpCardError::InternalError) + .map_err(Error::InternalError) } diff --git a/openpgp-card/src/card_do/historical.rs b/openpgp-card/src/card_do/historical.rs index 9b31906..b1b2aa8 100644 --- a/openpgp-card/src/card_do/historical.rs +++ b/openpgp-card/src/card_do/historical.rs @@ -4,7 +4,7 @@ //! 6 Historical Bytes use crate::card_do::{CardCapabilities, CardServiceData, Historical}; -use crate::errors::OpenpgpCardError; +use crate::Error; use anyhow::{anyhow, Result}; use std::convert::TryFrom; @@ -78,7 +78,7 @@ impl Historical { } impl TryFrom<&[u8]> for Historical { - type Error = OpenpgpCardError; + type Error = Error; fn try_from(data: &[u8]) -> Result { let len = data.len(); diff --git a/openpgp-card/src/card_do/key_generation_times.rs b/openpgp-card/src/card_do/key_generation_times.rs index dcf23bb..68e7c7a 100644 --- a/openpgp-card/src/card_do/key_generation_times.rs +++ b/openpgp-card/src/card_do/key_generation_times.rs @@ -7,9 +7,8 @@ use anyhow::anyhow; use chrono::{DateTime, NaiveDateTime, Utc}; use nom::{combinator, number::complete as number, sequence}; -use crate::card_do::KeyGenerationTime; -use crate::card_do::KeySet; -use crate::errors::OpenpgpCardError; +use crate::card_do::{KeyGenerationTime, KeySet}; +use crate::Error; impl From for DateTime { fn from(kg: KeyGenerationTime) -> Self { @@ -54,9 +53,7 @@ fn key_generation_set( )))(input) } -pub fn from( - input: &[u8], -) -> Result, OpenpgpCardError> { +pub fn from(input: &[u8]) -> Result, Error> { // List of generation dates/times of key pairs, binary. // 4 bytes, Big Endian each for Sig, Dec and Aut. Each // value shall be seconds since Jan 1, 1970. Default @@ -73,5 +70,5 @@ pub fn from( self::key_generation_set(input) .map(|res| res.1) .map_err(|err| anyhow!("Parsing failed: {:?}", err)) - .map_err(OpenpgpCardError::InternalError) + .map_err(Error::InternalError) } diff --git a/openpgp-card/src/card_do/mod.rs b/openpgp-card/src/card_do/mod.rs index 907f834..cc6db38 100644 --- a/openpgp-card/src/card_do/mod.rs +++ b/openpgp-card/src/card_do/mod.rs @@ -3,15 +3,12 @@ //! OpenPGP card data objects (DO) -use anyhow::{anyhow, Error, Result}; +use anyhow::{anyhow, Result}; use std::collections::HashSet; use std::convert::TryFrom; use std::convert::TryInto; -use crate::algorithm::Algo; -use crate::errors::OpenpgpCardError; -use crate::tlv::Tlv; -use crate::KeyType; +use crate::{algorithm::Algo, tlv::Tlv, Error, KeyType}; mod algo_attrs; mod algo_info; @@ -36,9 +33,7 @@ pub struct ApplicationRelatedData(pub(crate) Tlv); impl ApplicationRelatedData { /// Application identifier (AID), ISO 7816-4 - pub fn get_application_id( - &self, - ) -> Result { + pub fn get_application_id(&self) -> Result { // get from cached "application related data" let aid = self.0.find(&[0x4f].into()); @@ -50,7 +45,7 @@ impl ApplicationRelatedData { } /// Historical bytes - pub fn get_historical(&self) -> Result { + pub fn get_historical(&self) -> Result { // get from cached "application related data" let hist = self.0.find(&[0x5f, 0x52].into()); @@ -90,9 +85,7 @@ impl ApplicationRelatedData { } /// Extended Capabilities - pub fn get_extended_capabilities( - &self, - ) -> Result { + pub fn get_extended_capabilities(&self) -> Result { // get from cached "application related data" let ecap = self.0.find(&[0xc0].into()); @@ -136,9 +129,7 @@ impl ApplicationRelatedData { /// Fingerprint, per key type. /// Zero bytes indicate a not defined private key. - pub fn get_fingerprints( - &self, - ) -> Result, OpenpgpCardError> { + pub fn get_fingerprints(&self) -> Result, Error> { // Get from cached "application related data" let fp = self.0.find(&[0xc5].into()); @@ -156,7 +147,7 @@ impl ApplicationRelatedData { /// Generation dates/times of key pairs pub fn get_key_generation_times( &self, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { let kg = self.0.find(&[0xcd].into()); if let Some(kg) = kg { @@ -373,7 +364,9 @@ impl KeySet { } /// nom parsing helper -pub(crate) fn complete(result: nom::IResult<&[u8], O>) -> Result { +pub(crate) fn complete( + result: nom::IResult<&[u8], O>, +) -> Result { let (rem, output) = result.map_err(|err| anyhow!("Parsing failed: {:?}", err))?; if rem.is_empty() { diff --git a/openpgp-card/src/card_do/pw_status.rs b/openpgp-card/src/card_do/pw_status.rs index 032bfbb..0d3e97b 100644 --- a/openpgp-card/src/card_do/pw_status.rs +++ b/openpgp-card/src/card_do/pw_status.rs @@ -6,10 +6,10 @@ use anyhow::anyhow; use crate::card_do::PWStatus; -use crate::errors::OpenpgpCardError; +use crate::Error; impl PWStatus { - pub fn try_from(input: &[u8]) -> Result { + pub fn try_from(input: &[u8]) -> Result { if input.len() == 7 { let pw1_cds_multi = input[0] == 0x01; let pw1_pin_block = input[1] & 0x80 != 0; @@ -33,7 +33,7 @@ impl PWStatus { err_count_pw3, }) } else { - Err(OpenpgpCardError::InternalError(anyhow!( + Err(Error::InternalError(anyhow!( "Unexpected length of PW Status Bytes: {}", input.len() ))) diff --git a/openpgp-card/src/crypto_data.rs b/openpgp-card/src/crypto_data.rs index 793adc3..f3e0d4d 100644 --- a/openpgp-card/src/crypto_data.rs +++ b/openpgp-card/src/crypto_data.rs @@ -9,7 +9,7 @@ use anyhow::Result; use crate::algorithm::Algo; use crate::card_do::{Fingerprint, KeyGenerationTime}; -use crate::errors::OpenpgpCardError; +use crate::Error; /// A hash value that can be signed by the card. #[non_exhaustive] @@ -71,7 +71,7 @@ pub trait CardUploadableKey { fn get_ts(&self) -> KeyGenerationTime; /// fingerprint - fn get_fp(&self) -> Result; + fn get_fp(&self) -> Result; } /// Algorithm-independent container for private key material to upload to diff --git a/openpgp-card/src/errors.rs b/openpgp-card/src/errors.rs index d699dd2..a26fd13 100644 --- a/openpgp-card/src/errors.rs +++ b/openpgp-card/src/errors.rs @@ -3,24 +3,22 @@ //! Error types used by this crate. //! -//! [`OpenpgpCardError`] is a wrapper enum for all error types that are used. +//! [`Error`] is a wrapper enum for all error types that are used. //! //! The two main classes of errors are: //! - [`SmartcardError`], for problems on the reader/smartcard layer -//! - [`OcErrorStatus`], which models error statuses reported by the OpenPGP +//! - [`StatusByte`], which models error statuses reported by the OpenPGP //! card application -use thiserror::Error; - -/// Enum that wraps the different error types that this crate can return -#[derive(Error, Debug)] +/// Enum wrapper for the different error types of this crate +#[derive(thiserror::Error, Debug)] #[non_exhaustive] -pub enum OpenpgpCardError { +pub enum Error { #[error("Error interacting with smartcard: {0}")] Smartcard(SmartcardError), #[error("OpenPGP card error status: {0}")] - OcStatus(OcErrorStatus), + CardStatus(StatusByte), #[error("Command too long ({0} bytes)")] CommandTooLong(usize), @@ -32,22 +30,22 @@ pub enum OpenpgpCardError { InternalError(anyhow::Error), } -impl From for OpenpgpCardError { - fn from(oce: OcErrorStatus) -> Self { - OpenpgpCardError::OcStatus(oce) +impl From for Error { + fn from(oce: StatusByte) -> Self { + Error::CardStatus(oce) } } -impl From for OpenpgpCardError { +impl From for Error { fn from(ae: anyhow::Error) -> Self { - OpenpgpCardError::InternalError(ae) + Error::InternalError(ae) } } /// OpenPGP card "Status Byte" errors -#[derive(Error, Debug, PartialEq)] +#[derive(thiserror::Error, Debug, PartialEq)] #[non_exhaustive] -pub enum OcErrorStatus { +pub enum StatusByte { #[error("Selected file or DO in termination state")] TerminationState, @@ -118,40 +116,40 @@ pub enum OcErrorStatus { UnknownStatus(u8, u8), } -impl From<(u8, u8)> for OcErrorStatus { +impl From<(u8, u8)> for StatusByte { fn from(status: (u8, u8)) -> Self { match (status.0, status.1) { - (0x62, 0x85) => OcErrorStatus::TerminationState, + (0x62, 0x85) => StatusByte::TerminationState, (0x63, 0xC0..=0xCF) => { - OcErrorStatus::PasswordNotChecked(status.1 & 0xf) + StatusByte::PasswordNotChecked(status.1 & 0xf) } - (0x64, 0x02..=0x80) => OcErrorStatus::TriggeringByCard(status.1), - (0x65, 0x01) => OcErrorStatus::MemoryFailure, - (0x66, 0x00) => OcErrorStatus::SecurityRelatedIssues, - (0x67, 0x00) => OcErrorStatus::WrongLength, - (0x68, 0x81) => OcErrorStatus::LogicalChannelNotSupported, - (0x68, 0x82) => OcErrorStatus::SecureMessagingNotSupported, - (0x68, 0x83) => OcErrorStatus::LastCommandOfChainExpected, - (0x68, 0x84) => OcErrorStatus::CommandChainingUnsupported, - (0x69, 0x82) => OcErrorStatus::SecurityStatusNotSatisfied, - (0x69, 0x83) => OcErrorStatus::AuthenticationMethodBlocked, - (0x69, 0x85) => OcErrorStatus::ConditionOfUseNotSatisfied, - (0x69, 0x87) => OcErrorStatus::ExpectedSecureMessagingDOsMissing, - (0x69, 0x88) => OcErrorStatus::SMDataObjectsIncorrect, - (0x6A, 0x80) => OcErrorStatus::IncorrectParametersCommandDataField, - (0x6A, 0x82) => OcErrorStatus::FileOrApplicationNotFound, - (0x6A, 0x88) => OcErrorStatus::ReferencedDataNotFound, - (0x6B, 0x00) => OcErrorStatus::WrongParametersP1P2, - (0x6D, 0x00) => OcErrorStatus::INSNotSupported, - (0x6E, 0x00) => OcErrorStatus::CLANotSupported, - (0x6F, 0x00) => OcErrorStatus::NoPreciseDiagnosis, - _ => OcErrorStatus::UnknownStatus(status.0, status.1), + (0x64, 0x02..=0x80) => StatusByte::TriggeringByCard(status.1), + (0x65, 0x01) => StatusByte::MemoryFailure, + (0x66, 0x00) => StatusByte::SecurityRelatedIssues, + (0x67, 0x00) => StatusByte::WrongLength, + (0x68, 0x81) => StatusByte::LogicalChannelNotSupported, + (0x68, 0x82) => StatusByte::SecureMessagingNotSupported, + (0x68, 0x83) => StatusByte::LastCommandOfChainExpected, + (0x68, 0x84) => StatusByte::CommandChainingUnsupported, + (0x69, 0x82) => StatusByte::SecurityStatusNotSatisfied, + (0x69, 0x83) => StatusByte::AuthenticationMethodBlocked, + (0x69, 0x85) => StatusByte::ConditionOfUseNotSatisfied, + (0x69, 0x87) => StatusByte::ExpectedSecureMessagingDOsMissing, + (0x69, 0x88) => StatusByte::SMDataObjectsIncorrect, + (0x6A, 0x80) => StatusByte::IncorrectParametersCommandDataField, + (0x6A, 0x82) => StatusByte::FileOrApplicationNotFound, + (0x6A, 0x88) => StatusByte::ReferencedDataNotFound, + (0x6B, 0x00) => StatusByte::WrongParametersP1P2, + (0x6D, 0x00) => StatusByte::INSNotSupported, + (0x6E, 0x00) => StatusByte::CLANotSupported, + (0x6F, 0x00) => StatusByte::NoPreciseDiagnosis, + _ => StatusByte::UnknownStatus(status.0, status.1), } } } /// Errors on the smartcard/reader layer -#[derive(Error, Debug)] +#[derive(thiserror::Error, Debug)] #[non_exhaustive] pub enum SmartcardError { #[error("Failed to create a pcsc smartcard context {0}")] diff --git a/openpgp-card/src/keys.rs b/openpgp-card/src/keys.rs index c254771..2bdb4bc 100644 --- a/openpgp-card/src/keys.rs +++ b/openpgp-card/src/keys.rs @@ -16,8 +16,8 @@ use crate::crypto_data::{ CardUploadableKey, EccKey, EccPub, PrivateKeyMaterial, PublicKeyMaterial, RSAKey, RSAPub, }; -use crate::errors::OpenpgpCardError; use crate::tlv::{length::tlv_encode_length, value::Value, Tlv}; +use crate::Error; use crate::{apdu, KeyType}; /// Generate asymmetric key pair on the card. @@ -36,10 +36,10 @@ pub(crate) fn gen_key_with_metadata( &PublicKeyMaterial, KeyGenerationTime, KeyType, - ) -> Result, + ) -> Result, key_type: KeyType, algo: Option<&Algo>, -) -> Result<(PublicKeyMaterial, KeyGenerationTime), OpenpgpCardError> { +) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> { // set algo on card if it's Some if let Some(algo) = algo { card_app.set_algorithm_attributes(key_type, algo)?; @@ -63,7 +63,7 @@ pub(crate) fn gen_key_with_metadata( // Store creation timestamp (unix time format, limited to u32) let ts = time .duration_since(UNIX_EPOCH) - .map_err(|e| OpenpgpCardError::InternalError(anyhow!(e)))? + .map_err(|e| Error::InternalError(anyhow!(e)))? .as_secs() as u32; let ts = ts.into(); @@ -100,8 +100,7 @@ fn tlv_to_pubkey(tlv: &Tlv, algo: &Algo) -> Result { (_, _, _) => Err(anyhow!( "Unexpected public key material from card {:?}", tlv - ) - .into()), + )), } } @@ -112,7 +111,7 @@ fn tlv_to_pubkey(tlv: &Tlv, algo: &Algo) -> Result { pub(crate) fn generate_asymmetric_key_pair( card_app: &mut CardApp, key_type: KeyType, -) -> Result { +) -> Result { // generate key let crt = get_crt(key_type)?; let gen_key_cmd = commands::gen_key(crt.serialize().to_vec()); @@ -136,7 +135,7 @@ pub(crate) fn generate_asymmetric_key_pair( pub(crate) fn get_pub_key( card_app: &mut CardApp, key_type: KeyType, -) -> Result { +) -> Result { // algo let ard = card_app.get_app_data()?; // FIXME: caching let algo = ard.get_algorithm_attributes(key_type)?; @@ -163,7 +162,7 @@ pub(crate) fn key_import( key: Box, key_type: KeyType, algo_list: Option, -) -> Result<(), OpenpgpCardError> { +) -> Result<(), Error> { let (algo, key_cmd) = match key.get_key()? { PrivateKeyMaterial::R(rsa_key) => { // RSA bitsize @@ -262,7 +261,7 @@ fn get_card_algo_rsa( algo_list: AlgoInfo, key_type: KeyType, rsa_bits: u16, -) -> Result { +) -> Result { // Find suitable algorithm parameters (from card's list of algorithms). // FIXME: handle "no list available" (older cards?) // (Current algo parameters of the key slot should be used, then (?)) @@ -323,7 +322,7 @@ fn check_card_algo_ecc( fn ecc_key_import_cmd( ecc_key: Box, key_type: KeyType, -) -> Result { +) -> Result { let scalar_data = ecc_key.get_scalar(); let scalar_len = scalar_data.len() as u8; @@ -348,7 +347,7 @@ fn rsa_key_import_cmd( key_type: KeyType, rsa_key: Box, algo_attrs: &RsaAttrs, -) -> Result { +) -> Result { // Assemble key command, which contains three sub-TLV: // 1) "Control Reference Template" @@ -411,17 +410,13 @@ fn rsa_key_import_cmd( } /// Get "Control Reference Template" Tlv for `key_type` -fn get_crt(key_type: KeyType) -> Result { +fn get_crt(key_type: KeyType) -> Result { // "Control Reference Template" (0xB8 | 0xB6 | 0xA4) let tag = match key_type { KeyType::Decryption => 0xB8, KeyType::Signing => 0xB6, KeyType::Authentication => 0xA4, - _ => { - return Err(OpenpgpCardError::InternalError(anyhow!( - "Unexpected KeyType" - ))) - } + _ => return Err(Error::InternalError(anyhow!("Unexpected KeyType"))), }; Ok(Tlv::new([tag], Value::S(vec![]))) } diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 0b995a6..195d53f 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -32,12 +32,13 @@ mod apdu; mod card_app; pub mod card_do; pub mod crypto_data; -pub mod errors; +mod errors; mod keys; mod tlv; pub use crate::apdu::response::Response; pub use crate::card_app::CardApp; +pub use crate::errors::{Error, SmartcardError, StatusByte}; /// The CardClient trait defines communication with an OpenPGP card via a /// backend implementation (e.g. the pcsc backend in the crate diff --git a/pcsc/src/lib.rs b/pcsc/src/lib.rs index 8b87e3b..9caae04 100644 --- a/pcsc/src/lib.rs +++ b/pcsc/src/lib.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use anyhow::{anyhow, Result}; -use pcsc::{Card, Context, Error, Protocols, Scope, ShareMode}; +use pcsc::{Card, Context, Protocols, Scope, ShareMode}; -use openpgp_card::errors::{OpenpgpCardError, SmartcardError}; -use openpgp_card::{CardApp, CardCaps, CardClient, CardClientBox}; +use openpgp_card::{ + CardApp, CardCaps, CardClient, CardClientBox, Error, SmartcardError, +}; pub struct PcscClient { card: Card, @@ -51,7 +52,7 @@ impl PcscClient { let card = match ctx.connect(reader, ShareMode::Shared, Protocols::ANY) { Ok(card) => card, - Err(Error::NoSmartcard) => { + Err(pcsc::Error::NoSmartcard) => { continue; // try next reader } Err(err) => { @@ -94,16 +95,14 @@ impl PcscClient { } /// Try to select the OpenPGP application on a card - fn select(card_client: PcscClient) -> Result { + fn select(card_client: PcscClient) -> Result { let ccb = Box::new(card_client) as CardClientBox; let mut ca = CardApp::from(ccb); if ca.select().is_ok() { Ok(ca) } else { - Err(OpenpgpCardError::Smartcard( - SmartcardError::SelectOpenPGPCardFailed, - )) + Err(Error::Smartcard(SmartcardError::SelectOpenPGPCardFailed)) } } @@ -111,14 +110,14 @@ impl PcscClient { /// /// If multiple cards are connected, this will effectively be a random /// pick. You should consider using `open_by_ident` instead. - pub fn open_yolo() -> Result { + pub fn open_yolo() -> Result { for card in Self::unopened_cards()? { if let Ok(ca) = Self::select(card) { return Ok(ca.into()); } } - Err(OpenpgpCardError::Smartcard(SmartcardError::CardNotFound( + Err(Error::Smartcard(SmartcardError::CardNotFound( "No OpenPGP card found".to_string(), ))) } @@ -128,7 +127,7 @@ impl PcscClient { fn match_by_ident( mut ca: CardApp, ident: &str, - ) -> Result, OpenpgpCardError> { + ) -> Result, Error> { let ard = ca.get_app_data()?; let aid = ard.get_application_id()?; @@ -141,9 +140,7 @@ impl PcscClient { /// Returns the OpenPGP card that matches `ident`, if it is available. /// The OpenPGP application of the `CardClientBox` has been selected. - pub fn open_by_ident( - ident: &str, - ) -> Result { + pub fn open_by_ident(ident: &str) -> Result { for card in Self::unopened_cards()? { if let Ok(ca) = Self::select(card) { if let Some(matched_card) = @@ -154,7 +151,7 @@ impl PcscClient { } } - Err(OpenpgpCardError::Smartcard(SmartcardError::CardNotFound( + Err(Error::Smartcard(SmartcardError::CardNotFound( ident.to_string(), ))) } @@ -165,7 +162,7 @@ impl CardClient for PcscClient { let mut resp_buffer = vec![0; buf_size]; let resp = self.card.transmit(cmd, &mut resp_buffer).map_err(|e| { - OpenpgpCardError::Smartcard(SmartcardError::Error(format!( + Error::Smartcard(SmartcardError::Error(format!( "Transmit failed: {:?}", e ))) diff --git a/scdc/src/lib.rs b/scdc/src/lib.rs index 53d26b8..92ddb02 100644 --- a/scdc/src/lib.rs +++ b/scdc/src/lib.rs @@ -13,7 +13,7 @@ use sequoia_ipc::gnupg::{Agent, Context}; use std::sync::Mutex; use tokio::runtime::Runtime; -use openpgp_card::errors::OpenpgpCardError; +use openpgp_card::Error; use openpgp_card::{CardCaps, CardClient, CardClientBox}; lazy_static! { @@ -108,9 +108,7 @@ impl ScdClient { /// Create a CardClientBox object that uses an scdaemon instance as its /// backend. If multiple cards are available, scdaemon implicitly /// selects one. - pub fn open( - agent: Option, - ) -> Result { + pub fn open(agent: Option) -> Result { let card = ScdClient::new(agent, true)?; Ok(Box::new(card) as CardClientBox) } @@ -120,7 +118,7 @@ impl ScdClient { pub fn open_by_serial( agent: Option, serial: &str, - ) -> Result { + ) -> Result { let mut card = ScdClient::new(agent, true)?; card.select_card(serial)?;