diff --git a/card-functionality/src/list-cards.rs b/card-functionality/src/list-cards.rs index 3767b9e..3ce115c 100644 --- a/card-functionality/src/list-cards.rs +++ b/card-functionality/src/list-cards.rs @@ -9,8 +9,9 @@ use openpgp_card_sequoia::card::Open; fn main() -> Result<()> { println!("The following OpenPGP cards are connected to your system:"); - for card in PcscClient::cards()? { - let open = Open::open_card(card)?; + for ccb in PcscClient::cards()? { + let mut ca = ccb.into(); + let open = Open::open(&mut ca)?; println!(" {}", open.application_identifier()?.ident()); } diff --git a/card-functionality/src/tests.rs b/card-functionality/src/tests.rs index 7c9d917..54dac2d 100644 --- a/card-functionality/src/tests.rs +++ b/card-functionality/src/tests.rs @@ -15,6 +15,7 @@ use openpgp_card; use openpgp_card::algorithm::AlgoSimple; use openpgp_card::card_do::{KeyGenerationTime, Sex}; use openpgp_card::{CardApp, Error, KeyType, StatusBytes}; +use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::util::{ make_cert, public_key_material_to_key, public_to_fingerprint, }; @@ -220,7 +221,7 @@ pub fn test_upload_keys( /// Generate keys for each of the three KeyTypes pub fn test_keygen( - ca: &mut CardApp, + mut ca: &mut CardApp, param: &[&str], ) -> Result { ca.verify_pw3("12345678")?; @@ -253,8 +254,9 @@ pub fn test_keygen( public_key_material_to_key(&pkm, KeyType::Authentication, ts)?; // Generate a Cert for this set of generated keys - - let cert = make_cert(ca, key_sig, key_dec, key_aut)?; + let mut open = Open::open(&mut ca)?; + let cert = + make_cert(&mut open, key_sig, Some(key_dec), Some(key_aut), "123456")?; let armored = String::from_utf8(cert.armored().to_vec()?)?; let res = TestResult::Text(armored); diff --git a/openpgp-card-examples/src/bin/decrypt.rs b/openpgp-card-examples/src/bin/decrypt.rs index 9fa80e4..e938563 100644 --- a/openpgp-card-examples/src/bin/decrypt.rs +++ b/openpgp-card-examples/src/bin/decrypt.rs @@ -22,7 +22,8 @@ fn main() -> Result<(), Box> { let pin_file = &args[1]; let cert_file = &args[2]; - let mut open = Open::open_card(PcscClient::open_by_ident(&card_ident)?)?; + let mut ca = PcscClient::open_by_ident(&card_ident)?.into(); + let mut open = Open::open(&mut ca)?; let pin = std::fs::read_to_string(pin_file)?; diff --git a/openpgp-card-examples/src/bin/detach-sign.rs b/openpgp-card-examples/src/bin/detach-sign.rs index f48ebcc..f26981e 100644 --- a/openpgp-card-examples/src/bin/detach-sign.rs +++ b/openpgp-card-examples/src/bin/detach-sign.rs @@ -19,12 +19,12 @@ fn main() -> Result<(), Box> { return Ok(()); } - let test_card_ident = &args[0]; + let card_ident = &args[0]; let pin_file = &args[1]; let cert_file = &args[2]; - let mut open = - Open::open_card(PcscClient::open_by_ident(&test_card_ident)?)?; + let mut ca = PcscClient::open_by_ident(&card_ident)?.into(); + let mut open = Open::open(&mut ca)?; let pin = std::fs::read_to_string(pin_file)?; diff --git a/openpgp-card-sequoia/src/card.rs b/openpgp-card-sequoia/src/card.rs index 8262c4b..be2a39c 100644 --- a/openpgp-card-sequoia/src/card.rs +++ b/openpgp-card-sequoia/src/card.rs @@ -11,7 +11,7 @@ use sequoia_openpgp::packet::key::SecretParts; use sequoia_openpgp::policy::Policy; use sequoia_openpgp::Cert; -use openpgp_card::algorithm::{Algo, AlgoInfo}; +use openpgp_card::algorithm::{Algo, AlgoInfo, AlgoSimple}; use openpgp_card::card_do::{ ApplicationIdentifier, ApplicationRelatedData, CardholderRelatedData, ExtendedCapabilities, ExtendedLengthInfo, Fingerprint, HistoricalBytes, @@ -21,12 +21,14 @@ use openpgp_card::{CardApp, CardClientBox, Error, KeySet, KeyType, Response}; use crate::decryptor::CardDecryptor; use crate::signer::CardSigner; -use crate::util::vka_as_uploadable_key; +use crate::util::{public_to_fingerprint, vka_as_uploadable_key}; +use crate::PublicKey; +use openpgp_card::crypto_data::PublicKeyMaterial; /// Representation of an opened OpenPGP card in its base state (i.e. no /// passwords have been verified, default authorization applies). -pub struct Open { - card_app: CardApp, +pub struct Open<'a> { + card_app: &'a mut CardApp, // Cache of "application related data". // @@ -44,8 +46,16 @@ pub struct Open { pw3: bool, } -impl Open { - fn new(card_app: CardApp, ard: ApplicationRelatedData) -> Self { +impl<'a> Open<'a> { + pub fn open(card_app: &'a mut CardApp) -> Result { + let ard = card_app.get_application_related_data()?; + + card_app.init_caps(&ard)?; + + Ok(Self::new(card_app, ard)) + } + + fn new(card_app: &'a mut CardApp, ard: ApplicationRelatedData) -> Self { Self { card_app, ard, @@ -55,21 +65,6 @@ impl Open { } } - /// Set up connection to a CardClient (read and cache "application - /// related data"). - /// - /// The OpenPGP applet must already be opened in the CardClient. - pub fn open_card(ccb: CardClientBox) -> Result { - // read and cache "application related data" - let mut card_app = CardApp::from(ccb); - - let ard = card_app.get_application_related_data()?; - - card_app.init_caps(&ard)?; - - Ok(Self::new(card_app, ard)) - } - pub fn verify_user(&mut self, pin: &str) -> Result<(), Error> { let _ = self.card_app.verify_pw1(pin)?; self.pw1 = true; @@ -131,7 +126,7 @@ impl Open { } /// Get a view of the card authenticated for "User" commands. - pub fn user_card(&mut self) -> Option { + pub fn user_card<'b>(&'a mut self) -> Option> { if self.pw1 { Some(User { oc: self }) } else { @@ -140,7 +135,7 @@ impl Open { } /// Get a view of the card authenticated for Signing. - pub fn signing_card(&mut self) -> Option { + pub fn signing_card<'b>(&'b mut self) -> Option> { if self.pw1_sign { Some(Sign { oc: self }) } else { @@ -149,7 +144,7 @@ impl Open { } /// Get a view of the card authenticated for "Admin" commands. - pub fn admin_card(&mut self) -> Option { + pub fn admin_card<'b>(&'b mut self) -> Option> { if self.pw3 { Some(Admin { oc: self }) } else { @@ -288,11 +283,11 @@ impl Open { /// An OpenPGP card after successfully verifying PW1 in mode 82 /// (verification for user operations other than signing) -pub struct User<'a> { - oc: &'a mut Open, +pub struct User<'app, 'open> { + oc: &'open mut Open<'app>, } -impl User<'_> { +impl User<'_, '_> { pub fn decryptor( &mut self, cert: &Cert, @@ -304,11 +299,11 @@ impl User<'_> { /// An OpenPGP card after successfully verifying PW1 in mode 81 /// (verification for signing) -pub struct Sign<'a> { - oc: &'a mut Open, +pub struct Sign<'app, 'open> { + oc: &'open mut Open<'app>, } -impl Sign<'_> { +impl Sign<'_, '_> { pub fn signer( &mut self, cert: &Cert, @@ -319,14 +314,27 @@ impl Sign<'_> { CardSigner::new(&mut self.oc.card_app, cert, policy) } + + pub fn signer_from_pubkey(&mut self, pubkey: PublicKey) -> CardSigner { + // FIXME: depending on the setting in "PW1 Status byte", only one + // signature can be made after verification for signing + + CardSigner::with_pubkey(&mut self.oc.card_app, pubkey) + } } /// An OpenPGP card after successful verification of PW3 ("Admin privileges") -pub struct Admin<'a> { - oc: &'a mut Open, +pub struct Admin<'app, 'open> { + oc: &'open mut Open<'app>, } -impl Admin<'_> { +impl<'app, 'open> Admin<'app, 'open> { + pub fn get_open(&'_ mut self) -> &mut Open<'app> { + self.oc + } +} + +impl Admin<'_, '_> { pub fn set_name(&mut self, name: &str) -> Result { if name.len() >= 40 { return Err(anyhow!("name too long").into()); @@ -396,4 +404,16 @@ impl Admin<'_> { let key = vka_as_uploadable_key(vka, password); self.oc.card_app.key_import(key, key_type) } + + pub fn generate_key_simple( + &mut self, + key_type: KeyType, + algo: AlgoSimple, + ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> { + self.oc.card_app.generate_key_simple( + public_to_fingerprint, + key_type, + algo, + ) + } } diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index ffde17c..1607e08 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -17,7 +17,8 @@ //! //! # fn main() -> Result<(), Box> { //! for card in PcscClient::cards()? { -//! let open = Open::open_card(card)?; +//! let mut ca = card.into(); +//! let open = Open::open(&mut ca)?; //! println!("Found OpenPGP card with ident '{}'", //! open.application_identifier()?.ident()); //! } @@ -32,8 +33,8 @@ //! use openpgp_card_sequoia::card::Open; //! //! # fn main() -> Result<(), Box> { -//! let card = PcscClient::open_by_ident("abcd:12345678")?; -//! let mut open = Open::open_card(card)?; +//! let mut ca = PcscClient::open_by_ident("abcd:12345678")?.into(); +//! let mut open = Open::open(&mut ca)?; //! # Ok(()) //! # } //! ``` @@ -54,8 +55,8 @@ //! # fn main() -> Result<(), Box> { //! // Open card via PCSC //! use sequoia_openpgp::policy::StandardPolicy; -//! let card = PcscClient::open_by_ident("abcd:12345678")?; -//! let mut open = Open::open_card(card)?; +//! let mut ca = PcscClient::open_by_ident("abcd:12345678")?.into(); +//! let mut open = Open::open(&mut ca)?; //! //! // Get authorization for user access to the card with password //! open.verify_user("123456")?; @@ -95,8 +96,8 @@ //! # fn main() -> Result<(), Box> { //! // Open card via PCSC //! use sequoia_openpgp::policy::StandardPolicy; -//! let card = PcscClient::open_by_ident("abcd:12345678")?; -//! let mut open = Open::open_card(card)?; +//! let mut ca = PcscClient::open_by_ident("abcd:12345678")?.into(); +//! let mut open = Open::open(&mut ca)?; //! //! // Get authorization for signing access to the card with password //! open.verify_user_for_signing("123456")?; @@ -125,8 +126,8 @@ //! //! # fn main() -> Result<(), Box> { //! // Open card via PCSC -//! let card = PcscClient::open_by_ident("abcd:12345678")?; -//! let mut open = Open::open_card(card)?; +//! let mut ca = PcscClient::open_by_ident("abcd:12345678")?.into(); +//! let mut open = Open::open(&mut ca)?; //! //! // Get authorization for admin access to the card with password //! open.verify_admin("12345678")?; diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index eff010c..1242f9e 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -21,6 +21,7 @@ use openpgp_card_sequoia::sq_util::{decryption_helper, sign_helper}; // const TEST_KEY_PATH: &str = "example/test4k.sec"; // const TEST_ENC_MSG: &str = "example/encrypted_to_rsa4k.asc"; +// const TEST_KEY_PATH: &str = "example/nist521.sec"; // const TEST_KEY_PATH: &str = "example/nist521.sec"; // const TEST_ENC_MSG: &str = "example/encrypted_to_nist521.asc"; @@ -34,8 +35,8 @@ fn main() -> Result<(), Box> { let test_card_ident = env::var("TEST_CARD_IDENT"); if let Ok(test_card_ident) = test_card_ident { - let mut open = - Open::open_card(PcscClient::open_by_ident(&test_card_ident)?)?; + let mut card = PcscClient::open_by_ident(&test_card_ident)?.into(); + let mut open = Open::open(&mut card)?; // card metadata @@ -149,9 +150,8 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for decrypt // ----------------------------- - - let mut open = - Open::open_card(PcscClient::open_by_ident(&test_card_ident)?)?; + let mut card = PcscClient::open_by_ident(&test_card_ident)?.into(); + let mut open = Open::open(&mut card)?; // Check that we're still using the expected card let app_id = open.application_identifier()?; @@ -189,8 +189,8 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for signing // ----------------------------- - let mut open = - Open::open_card(PcscClient::open_by_ident(&test_card_ident)?)?; + let mut card = PcscClient::open_by_ident(&test_card_ident)?.into(); + let mut open = Open::open(&mut card)?; // Sign open.verify_user_for_signing("123456")?; @@ -220,7 +220,8 @@ fn main() -> Result<(), Box> { println!("The following OpenPGP cards are connected to your system:"); for card in PcscClient::cards()? { - let open = Open::open_card(card)?; + let mut card = card.into(); + let open = Open::open(&mut card)?; println!(" {}", open.application_identifier()?.ident()); } } diff --git a/openpgp-card-sequoia/src/util.rs b/openpgp-card-sequoia/src/util.rs index defa580..5f49a14 100644 --- a/openpgp-card-sequoia/src/util.rs +++ b/openpgp-card-sequoia/src/util.rs @@ -30,6 +30,7 @@ use openpgp_card::card_do::{Fingerprint, KeyGenerationTime}; use openpgp_card::crypto_data::{CardUploadableKey, PublicKeyMaterial}; use openpgp_card::{CardApp, Error, KeyType}; +use crate::card::Open; use crate::privkey::SequoiaKey; use crate::signer::CardSigner; use crate::{decryptor, signer, PublicKey}; @@ -37,16 +38,13 @@ use crate::{decryptor, signer, PublicKey}; /// Create a Cert from the three subkeys on a card. /// (Calling this multiple times will result in different Certs!) /// -/// FIXME: contains hardcoded default passwords! -/// -/// FIXME: make dec/auth keys optional -/// /// FIXME: accept optional metadata for user_id(s)? -pub fn make_cert( - ca: &mut CardApp, +pub fn make_cert<'a, 'app>( + open: &'a mut Open<'app>, key_sig: PublicKey, - key_dec: PublicKey, - key_aut: PublicKey, + key_dec: Option, + key_aut: Option, + pw1: &str, ) -> Result { let mut pp = vec![]; @@ -54,65 +52,74 @@ pub fn make_cert( let pri = PrimaryRole::convert_key(key_sig.clone()); pp.push(Packet::from(pri)); - // 2) add decryption key as subkey - let sub_dec = SubordinateRole::convert_key(key_dec); - pp.push(Packet::from(sub_dec.clone())); + if let Some(key_dec) = key_dec { + // 2) add decryption key as subkey + let sub_dec = SubordinateRole::convert_key(key_dec); + pp.push(Packet::from(sub_dec.clone())); - // Temporary version of the cert - let cert = Cert::try_from(pp.clone())?; + // Temporary version of the cert + let cert = Cert::try_from(pp.clone())?; - // 3) make binding, sign with card -> add - { - let signing_builder = - SignatureBuilder::new(SignatureType::SubkeyBinding) - .set_signature_creation_time(SystemTime::now())? - .set_key_validity_period(std::time::Duration::new(0, 0))? - .set_key_flags( - KeyFlags::empty() - .set_storage_encryption() - .set_transport_encryption(), - )?; + // 3) make binding, sign with card -> add + { + let signing_builder = + SignatureBuilder::new(SignatureType::SubkeyBinding) + .set_signature_creation_time(SystemTime::now())? + .set_key_validity_period(std::time::Duration::new(0, 0))? + .set_key_flags( + KeyFlags::empty() + .set_storage_encryption() + .set_transport_encryption(), + )?; - // Allow signing on the card - ca.verify_pw1_for_signing("123456")?; + // Allow signing on the card + open.verify_user_for_signing(pw1)?; + if let Some(mut sign) = open.signing_card() { + // Card-backed signer for bindings + let mut card_signer = sign.signer_from_pubkey(key_sig.clone()); - // Card-backed signer for bindings - let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone()); + let signing_bsig: Packet = sub_dec + .bind(&mut card_signer, &cert, signing_builder)? + .into(); - let signing_bsig: Packet = sub_dec - .bind(&mut card_signer, &cert, signing_builder)? - .into(); - - pp.push(signing_bsig); + pp.push(signing_bsig); + } + } } - // 4) add auth subkey - let sub_aut = SubordinateRole::convert_key(key_aut); - pp.push(Packet::from(sub_aut.clone())); + if let Some(key_aut) = key_aut { + // 4) add auth subkey + let sub_aut = SubordinateRole::convert_key(key_aut); + pp.push(Packet::from(sub_aut.clone())); - // 5) make, sign binding -> add - { - let signing_builder = - SignatureBuilder::new(SignatureType::SubkeyBinding) - .set_signature_creation_time(SystemTime::now())? - .set_key_validity_period(std::time::Duration::new(0, 0))? - .set_key_flags(KeyFlags::empty().set_authentication())?; + // 5) make, sign binding -> add + { + let signing_builder = + SignatureBuilder::new(SignatureType::SubkeyBinding) + .set_signature_creation_time(SystemTime::now())? + .set_key_validity_period(std::time::Duration::new(0, 0))? + .set_key_flags(KeyFlags::empty().set_authentication())?; - // Allow signing on the card - ca.verify_pw1_for_signing("123456")?; + // Allow signing on the card + open.verify_user_for_signing(pw1)?; + if let Some(mut sign) = open.signing_card() { + // Card-backed signer for bindings + let mut card_signer = sign.signer_from_pubkey(key_sig.clone()); - // Card-backed signer for bindings - let mut card_signer = CardSigner::with_pubkey(ca, key_sig.clone()); + // Temporary version of the cert + let cert = Cert::try_from(pp.clone())?; - let signing_bsig: Packet = sub_aut - .bind(&mut card_signer, &cert, signing_builder)? - .into(); + let signing_bsig: Packet = sub_aut + .bind(&mut card_signer, &cert, signing_builder)? + .into(); - pp.push(signing_bsig); + pp.push(signing_bsig); + } + } } // 6) add user id from name / email - let cardholder = ca.get_cardholder_related_data()?; + let cardholder = open.cardholder_related_data()?; // FIXME: process name field? accept email as argument?! let uid: UserID = @@ -132,15 +139,20 @@ pub fn make_cert( )?; // Allow signing on the card - ca.verify_pw1_for_signing("123456")?; + open.verify_user_for_signing(pw1)?; - // Card-backed signer for bindings - let mut card_signer = CardSigner::with_pubkey(ca, key_sig); + if let Some(mut sign) = open.signing_card() { + // Card-backed signer for bindings + let mut card_signer = sign.signer_from_pubkey(key_sig); - let signing_bsig: Packet = - uid.bind(&mut card_signer, &cert, signing_builder)?.into(); + // Temporary version of the cert + let cert = Cert::try_from(pp.clone())?; - pp.push(signing_bsig); + let signing_bsig: Packet = + uid.bind(&mut card_signer, &cert, signing_builder)?.into(); + + pp.push(signing_bsig); + } } Cert::try_from(pp) diff --git a/tools/src/bin/opgpcard-pin/main.rs b/tools/src/bin/opgpcard-pin/main.rs index 25c110c..d38a37b 100644 --- a/tools/src/bin/opgpcard-pin/main.rs +++ b/tools/src/bin/opgpcard-pin/main.rs @@ -4,7 +4,7 @@ use anyhow::Result; use structopt::StructOpt; -use openpgp_card::{Error, Response, StatusBytes}; +use openpgp_card::{Error, StatusBytes}; use openpgp_card_pcsc::PcscClient; use openpgp_card_sequoia::card::Open; @@ -13,8 +13,8 @@ mod cli; fn main() -> Result<(), Box> { let cli = cli::Cli::from_args(); - let ccb = PcscClient::open_by_ident(&cli.ident)?; - let mut card = Open::open_card(ccb)?; + let mut card = PcscClient::open_by_ident(&cli.ident)?.into(); + let mut open = Open::open(&mut card)?; match cli.cmd { cli::Command::SetUserPin {} => { @@ -23,7 +23,7 @@ fn main() -> Result<(), Box> { rpassword::read_password_from_tty(Some("Enter user PIN: "))?; // verify pin - card.verify_user(&pin)?; + open.verify_user(&pin)?; println!("PIN was accepted by the card.\n"); // get new user pin @@ -39,10 +39,12 @@ fn main() -> Result<(), Box> { } // set new user pin - let res = card.change_user_pin(&pin, &newpin1); + let res = open.change_user_pin(&pin, &newpin1); if res.is_err() { println!("\nFailed to change the user PIN!"); - print_gnuk_note(res, card)?; + if let Err(err) = res { + print_gnuk_note(err, &open)?; + } } else { println!("\nUser PIN has been set."); } @@ -53,7 +55,7 @@ fn main() -> Result<(), Box> { rpassword::read_password_from_tty(Some("Enter admin PIN: "))?; // verify pin - card.verify_admin(&pin)?; + open.verify_admin(&pin)?; // get new admin pin let newpin1 = rpassword::read_password_from_tty(Some( @@ -68,7 +70,7 @@ fn main() -> Result<(), Box> { } // set new user pin - card.change_admin_pin(&pin, &newpin1)?; + open.change_admin_pin(&pin, &newpin1)?; println!("\nAdmin PIN has been set."); } @@ -78,10 +80,10 @@ fn main() -> Result<(), Box> { rpassword::read_password_from_tty(Some("Enter admin PIN: "))?; // verify admin pin - card.verify_admin(&pin)?; + open.verify_admin(&pin)?; println!("PIN was accepted by the card.\n"); - if let Some(mut admin) = card.admin_card() { + if let Some(mut admin) = open.admin_card() { // ask user for new resetting code let newpin1 = rpassword::read_password_from_tty(Some( "Enter new resetting code: ", @@ -113,7 +115,7 @@ fn main() -> Result<(), Box> { ))?; // verify pin - card.verify_admin(&pin)?; + open.verify_admin(&pin)?; println!("PIN was accepted by the card.\n"); None @@ -142,9 +144,9 @@ fn main() -> Result<(), Box> { let res = if let Some(rst) = rst { // reset to new user pin - card.reset_user_pin(&rst, &newpin1) + open.reset_user_pin(&rst, &newpin1) } else { - if let Some(mut admin) = card.admin_card() { + if let Some(mut admin) = open.admin_card() { admin.reset_user_pin(&newpin1) } else { return Err(anyhow::anyhow!( @@ -156,7 +158,9 @@ fn main() -> Result<(), Box> { if res.is_err() { println!("\nFailed to change the user PIN!"); - print_gnuk_note(res, card)?; + if let Err(err) = res { + print_gnuk_note(err, &open)?; + } } else { println!("\nUser PIN has been set."); } @@ -172,10 +176,11 @@ fn main() -> Result<(), Box> { /// This fn checks for Gnuk's Status code and the case that no keys exist /// on the card, and prints a note to the user, pointing out that the /// absence of keys on the card might be the reason for the error they get. -fn print_gnuk_note(res: Result, card: Open) -> Result<()> { - if let Err(Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied)) = - res - { +fn print_gnuk_note(err: Error, card: &Open) -> Result<()> { + if matches!( + err, + Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied) + ) { // check if no keys exist on the card let fps = card.fingerprints()?; if fps.signature() == None diff --git a/tools/src/bin/opgpcard/main.rs b/tools/src/bin/opgpcard/main.rs index 1db95dd..6b0d937 100644 --- a/tools/src/bin/opgpcard/main.rs +++ b/tools/src/bin/opgpcard/main.rs @@ -8,11 +8,14 @@ use structopt::StructOpt; use sequoia_openpgp::parse::{stream::DecryptorBuilder, Parse}; use sequoia_openpgp::policy::StandardPolicy; use sequoia_openpgp::serialize::stream::{Armorer, Message, Signer}; +use sequoia_openpgp::serialize::SerializeInto; use sequoia_openpgp::Cert; -use openpgp_card_sequoia::card::Admin; +use openpgp_card_sequoia::card::{Admin, Open}; use openpgp_card_sequoia::sq_util; +use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key}; +use openpgp_card::algorithm::AlgoSimple; use openpgp_card::{card_do::Sex, KeyType}; mod cli; @@ -67,14 +70,18 @@ fn main() -> Result<(), Box> { pin_file, cmd, } => { - let mut open = util::open_card(&ident)?; - let mut admin = util::get_admin(&mut open, &pin_file)?; + let mut card = util::open_card(&ident)?.into(); + let mut open = Open::open(&mut card)?; match cmd { cli::AdminCommand::Name { name } => { + let mut admin = util::get_admin(&mut open, &pin_file)?; + let _ = admin.set_name(&name)?; } cli::AdminCommand::Url { url } => { + let mut admin = util::get_admin(&mut open, &pin_file)?; + let _ = admin.set_url(&url)?; } cli::AdminCommand::Import { @@ -83,6 +90,7 @@ fn main() -> Result<(), Box> { dec_fp, auth_fp, } => { + let admin = util::get_admin(&mut open, &pin_file)?; let key = Cert::from_file(keyfile)?; if (&sig_fp, &dec_fp, &auth_fp) == (&None, &None, &None) { @@ -109,7 +117,9 @@ fn list_cards() -> Result<()> { println!("Available OpenPGP cards:"); for card in cards { - println!(" {}", card.application_identifier()?.ident()); + let mut card = card.into(); + let open = Open::open(&mut card)?; + println!(" {}", open.application_identifier()?.ident()); } } else { println!("No OpenPGP cards found."); @@ -118,7 +128,7 @@ fn list_cards() -> Result<()> { } fn print_status(ident: Option, verbose: bool) -> Result<()> { - let mut open = if let Some(ident) = ident { + let ccb = if let Some(ident) = ident { util::open_card(&ident)? } else { let mut cards = util::cards()?; @@ -128,6 +138,8 @@ fn print_status(ident: Option, verbose: bool) -> Result<()> { return Err(anyhow::anyhow!("Found {} cards", cards.len()).into()); } }; + let mut card = ccb.into(); + let mut open = Open::open(&mut card)?; print!("OpenPGP card {}", open.application_identifier()?.ident()); @@ -258,7 +270,9 @@ fn decrypt( let input = util::open_or_stdin(input.as_deref())?; - let mut open = util::open_card(&ident)?; + let mut card = util::open_card(&ident)?.into(); + let mut open = Open::open(&mut card)?; + let mut user = util::get_user(&mut open, &pin_file)?; let d = user.decryptor(&cert, &p)?; @@ -281,7 +295,9 @@ fn sign_detached( let mut input = util::open_or_stdin(input.as_deref())?; - let mut open = util::open_card(&ident)?; + let mut card = util::open_card(&ident)?.into(); + let mut open = Open::open(&mut card)?; + let mut sign = util::get_sign(&mut open, &pin_file)?; let s = sign.signer(&cert, &p)?; @@ -296,7 +312,8 @@ fn sign_detached( fn factory_reset(ident: &str) -> Result<()> { println!("Resetting Card {}", ident); - util::open_card(ident)?.factory_reset() + let mut card = util::open_card(ident)?.into(); + Open::open(&mut card)?.factory_reset() } fn key_import_yolo(mut admin: Admin, key: &Cert) -> Result<()> { diff --git a/tools/src/bin/opgpcard/util.rs b/tools/src/bin/opgpcard/util.rs index 78e7181..442ae11 100644 --- a/tools/src/bin/opgpcard/util.rs +++ b/tools/src/bin/opgpcard/util.rs @@ -3,54 +3,47 @@ use anyhow::{Context, Result}; -use openpgp_card::Error; +use openpgp_card::{CardClientBox, Error}; use openpgp_card_pcsc::PcscClient; use openpgp_card_sequoia::card::{Admin, Open, Sign, User}; use std::path::Path; -pub(crate) fn cards() -> Result> { - let mut cards = vec![]; - - for card in PcscClient::cards()? { - cards.push(Open::open_card(card)?); - } - - Ok(cards) +pub(crate) fn cards() -> Result> { + PcscClient::cards() } -pub(crate) fn open_card(ident: &str) -> Result { - let ccb = PcscClient::open_by_ident(ident)?; - Open::open_card(ccb) +pub(crate) fn open_card(ident: &str) -> Result { + PcscClient::open_by_ident(ident) } -pub(crate) fn get_user<'a>( - open: &'a mut Open, +pub(crate) fn get_user<'app, 'open>( + open: &'app mut Open<'app>, pin_file: &Path, -) -> Result, Box> { +) -> Result, Box> { open.verify_user(&get_pin(pin_file)?)?; open.user_card() .ok_or_else(|| anyhow::anyhow!("Couldn't get user access").into()) } -pub(crate) fn get_sign<'a>( - open: &'a mut Open, +pub(crate) fn get_sign<'app, 'open>( + open: &'app mut Open<'app>, pin_file: &Path, -) -> Result, Box> { +) -> Result, Box> { open.verify_user_for_signing(&get_pin(pin_file)?)?; open.signing_card() .ok_or_else(|| anyhow::anyhow!("Couldn't get sign access").into()) } -pub(crate) fn get_admin<'a>( - open: &'a mut Open, +pub(crate) fn get_admin<'app, 'open>( + open: &'app mut Open<'app>, pin_file: &Path, -) -> Result, Box> { +) -> Result, Box> { open.verify_admin(&get_pin(pin_file)?)?; open.admin_card() .ok_or_else(|| anyhow::anyhow!("Couldn't get admin access").into()) } -fn get_pin(pin_file: &Path) -> Result { +pub(crate) fn get_pin(pin_file: &Path) -> Result { let pin = std::fs::read_to_string(pin_file)?; Ok(pin.trim().to_string()) }