Refactor "Open" to use a borrowed CardApp (instead of owning the CardApp).

This commit is contained in:
Heiko Schaefer 2021-11-02 21:31:15 +01:00
parent 8dd83b6c55
commit 8674b0e65c
11 changed files with 218 additions and 165 deletions

View file

@ -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());
}

View file

@ -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<TestOutput, TestError> {
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);

View file

@ -22,7 +22,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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)?;

View file

@ -19,12 +19,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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)?;

View file

@ -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<Self, Error> {
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<Self, Error> {
// 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<User> {
pub fn user_card<'b>(&'a mut self) -> Option<User<'a, 'b>> {
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<Sign> {
pub fn signing_card<'b>(&'b mut self) -> Option<Sign<'a, 'b>> {
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<Admin> {
pub fn admin_card<'b>(&'b mut self) -> Option<Admin<'a, 'b>> {
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<Response, Error> {
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,
)
}
}

View file

@ -17,7 +17,8 @@
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! 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<dyn std::error::Error>> {
//! 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<dyn std::error::Error>> {
//! // 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<dyn std::error::Error>> {
//! // 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<dyn std::error::Error>> {
//! // 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")?;

View file

@ -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<dyn Error>> {
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<dyn Error>> {
// -----------------------------
// 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<dyn Error>> {
// -----------------------------
// 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<dyn Error>> {
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());
}
}

View file

@ -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<PublicKey>,
key_aut: Option<PublicKey>,
pw1: &str,
) -> Result<Cert> {
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)

View file

@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
}
// 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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
}
// 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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
))?;
// 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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
/// 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<Response, Error>, 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

View file

@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<String>, 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<String>, 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<()> {

View file

@ -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<Vec<Open>> {
let mut cards = vec![];
for card in PcscClient::cards()? {
cards.push(Open::open_card(card)?);
}
Ok(cards)
pub(crate) fn cards() -> Result<Vec<CardClientBox>> {
PcscClient::cards()
}
pub(crate) fn open_card(ident: &str) -> Result<Open, Error> {
let ccb = PcscClient::open_by_ident(ident)?;
Open::open_card(ccb)
pub(crate) fn open_card(ident: &str) -> Result<CardClientBox, Error> {
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<User<'a>, Box<dyn std::error::Error>> {
) -> Result<User<'app, 'open>, Box<dyn std::error::Error>> {
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<Sign<'a>, Box<dyn std::error::Error>> {
) -> Result<Sign<'app, 'open>, Box<dyn std::error::Error>> {
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<Admin<'a>, Box<dyn std::error::Error>> {
) -> Result<Admin<'app, 'open>, Box<dyn std::error::Error>> {
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<String> {
pub(crate) fn get_pin(pin_file: &Path) -> Result<String> {
let pin = std::fs::read_to_string(pin_file)?;
Ok(pin.trim().to_string())
}