Rename CardClient -> CardTransaction.

This commit is contained in:
Heiko Schaefer 2022-02-17 18:48:17 +01:00
parent 5b2979874b
commit 5133051626
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
13 changed files with 234 additions and 243 deletions

View file

@ -15,7 +15,7 @@ use sequoia_openpgp::Cert;
use openpgp_card; use openpgp_card;
use openpgp_card::algorithm::AlgoSimple; use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::card_do::{KeyGenerationTime, Sex}; use openpgp_card::card_do::{KeyGenerationTime, Sex};
use openpgp_card::{CardClient, Error, KeyType, StatusBytes}; use openpgp_card::{CardTransaction, Error, KeyType, StatusBytes};
use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::card::Open;
use openpgp_card_sequoia::util::{ use openpgp_card_sequoia::util::{
make_cert, public_key_material_to_key, public_to_fingerprint, make_cert, public_key_material_to_key, public_to_fingerprint,
@ -53,7 +53,7 @@ pub enum TestError {
/// Run after each "upload keys", if key *was* uploaded (?) /// Run after each "upload keys", if key *was* uploaded (?)
pub fn test_decrypt( pub fn test_decrypt(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
param: &[&str], param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
assert_eq!( assert_eq!(
@ -65,12 +65,12 @@ pub fn test_decrypt(
let cert = Cert::from_str(param[0])?; let cert = Cert::from_str(param[0])?;
let msg = param[1].to_string(); let msg = param[1].to_string();
card_client.verify_pw1("123456")?; card_tx.verify_pw1("123456")?;
let p = StandardPolicy::new(); let p = StandardPolicy::new();
let res = openpgp_card_sequoia::util::decrypt( let res = openpgp_card_sequoia::util::decrypt(
card_client, card_tx,
&cert, &cert,
msg.into_bytes(), msg.into_bytes(),
&p, &p,
@ -84,21 +84,18 @@ pub fn test_decrypt(
/// Run after each "upload keys", if key *was* uploaded (?) /// Run after each "upload keys", if key *was* uploaded (?)
pub fn test_sign( pub fn test_sign(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
param: &[&str], param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
assert_eq!(param.len(), 1, "test_sign needs a filename for 'cert'"); assert_eq!(param.len(), 1, "test_sign needs a filename for 'cert'");
card_client.verify_pw1_for_signing("123456")?; card_tx.verify_pw1_for_signing("123456")?;
let cert = Cert::from_str(param[0])?; let cert = Cert::from_str(param[0])?;
let msg = "Hello world, I am signed."; let msg = "Hello world, I am signed.";
let sig = openpgp_card_sequoia::util::sign( let sig =
card_client, openpgp_card_sequoia::util::sign(card_tx, &cert, &mut msg.as_bytes())?;
&cert,
&mut msg.as_bytes(),
)?;
// validate sig // validate sig
assert!(util::verify_sig(&cert, msg.as_bytes(), sig.as_bytes())?); assert!(util::verify_sig(&cert, msg.as_bytes(), sig.as_bytes())?);
@ -107,10 +104,10 @@ pub fn test_sign(
} }
fn check_key_upload_metadata( fn check_key_upload_metadata(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
meta: &[(String, KeyGenerationTime)], meta: &[(String, KeyGenerationTime)],
) -> Result<()> { ) -> Result<()> {
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
// check fingerprints // check fingerprints
let card_fp = ard.fingerprints()?; let card_fp = ard.fingerprints()?;
@ -151,10 +148,10 @@ fn check_key_upload_algo_attrs() -> Result<()> {
} }
pub fn test_print_caps( pub fn test_print_caps(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let aid = ard.application_id()?; let aid = ard.application_id()?;
println!("aid: {:#x?}", aid); println!("aid: {:#x?}", aid);
@ -172,17 +169,17 @@ pub fn test_print_caps(
} }
pub fn test_print_algo_info( pub fn test_print_algo_info(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let dec = ard.algorithm_attributes(KeyType::Decryption)?; let dec = ard.algorithm_attributes(KeyType::Decryption)?;
println!("Current algorithm for the decrypt slot: {}", dec); println!("Current algorithm for the decrypt slot: {}", dec);
println!(); println!();
let algo = card_client.algorithm_information(); let algo = card_tx.algorithm_information();
if let Ok(Some(algo)) = algo { if let Ok(Some(algo)) = algo {
println!("Card algorithm list:\n{}", algo); println!("Card algorithm list:\n{}", algo);
} }
@ -191,7 +188,7 @@ pub fn test_print_algo_info(
} }
pub fn test_upload_keys( pub fn test_upload_keys(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
param: &[&str], param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
assert_eq!( assert_eq!(
@ -200,16 +197,16 @@ pub fn test_upload_keys(
"test_upload_keys needs a filename for 'cert'" "test_upload_keys needs a filename for 'cert'"
); );
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
let cert = Cert::from_file(param[0])?; let cert = Cert::from_file(param[0])?;
let p = StandardPolicy::new(); let p = StandardPolicy::new();
let meta = util::upload_subkeys(card_client, &cert, &p) let meta = util::upload_subkeys(card_tx, &cert, &p)
.map_err(|e| TestError::KeyUploadError(param[0].to_string(), e))?; .map_err(|e| TestError::KeyUploadError(param[0].to_string(), e))?;
check_key_upload_metadata(card_client, &meta)?; check_key_upload_metadata(card_tx, &meta)?;
// FIXME: implement // FIXME: implement
check_key_upload_algo_attrs()?; check_key_upload_algo_attrs()?;
@ -219,10 +216,10 @@ pub fn test_upload_keys(
/// Generate keys for each of the three KeyTypes /// Generate keys for each of the three KeyTypes
pub fn test_keygen( pub fn test_keygen(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
param: &[&str], param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
// Generate all three subkeys on card // Generate all three subkeys on card
let algo = param[0]; let algo = param[0];
@ -230,7 +227,7 @@ pub fn test_keygen(
let alg = AlgoSimple::try_from(algo)?; let alg = AlgoSimple::try_from(algo)?;
println!(" Generate subkey for Signing"); println!(" Generate subkey for Signing");
let (pkm, ts) = card_client.generate_key_simple( let (pkm, ts) = card_tx.generate_key_simple(
public_to_fingerprint, public_to_fingerprint,
KeyType::Signing, KeyType::Signing,
alg, alg,
@ -238,7 +235,7 @@ pub fn test_keygen(
let key_sig = public_key_material_to_key(&pkm, KeyType::Signing, ts)?; let key_sig = public_key_material_to_key(&pkm, KeyType::Signing, ts)?;
println!(" Generate subkey for Decryption"); println!(" Generate subkey for Decryption");
let (pkm, ts) = card_client.generate_key_simple( let (pkm, ts) = card_tx.generate_key_simple(
public_to_fingerprint, public_to_fingerprint,
KeyType::Decryption, KeyType::Decryption,
alg, alg,
@ -246,7 +243,7 @@ pub fn test_keygen(
let key_dec = public_key_material_to_key(&pkm, KeyType::Decryption, ts)?; let key_dec = public_key_material_to_key(&pkm, KeyType::Decryption, ts)?;
println!(" Generate subkey for Authentication"); println!(" Generate subkey for Authentication");
let (pkm, ts) = card_client.generate_key_simple( let (pkm, ts) = card_tx.generate_key_simple(
public_to_fingerprint, public_to_fingerprint,
KeyType::Authentication, KeyType::Authentication,
alg, alg,
@ -255,7 +252,7 @@ pub fn test_keygen(
public_key_material_to_key(&pkm, KeyType::Authentication, ts)?; public_key_material_to_key(&pkm, KeyType::Authentication, ts)?;
// Generate a Cert for this set of generated keys // Generate a Cert for this set of generated keys
let mut open = Open::new(card_client)?; let mut open = Open::new(card_tx)?;
let cert = make_cert( let cert = make_cert(
&mut open, &mut open,
key_sig, key_sig,
@ -273,15 +270,15 @@ pub fn test_keygen(
/// Construct public key based on data from the card /// Construct public key based on data from the card
pub fn test_get_pub( pub fn test_get_pub(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let key_gen = ard.key_generation_times()?; let key_gen = ard.key_generation_times()?;
// -- // --
let sig = card_client.public_key(KeyType::Signing)?; let sig = card_tx.public_key(KeyType::Signing)?;
let ts = key_gen.signature().unwrap().get().into(); let ts = key_gen.signature().unwrap().get().into();
let key = public_key_material_to_key(&sig, KeyType::Signing, ts)?; let key = public_key_material_to_key(&sig, KeyType::Signing, ts)?;
@ -289,7 +286,7 @@ pub fn test_get_pub(
// -- // --
let dec = card_client.public_key(KeyType::Decryption)?; let dec = card_tx.public_key(KeyType::Decryption)?;
let ts = key_gen.decryption().unwrap().get().into(); let ts = key_gen.decryption().unwrap().get().into();
let key = public_key_material_to_key(&dec, KeyType::Decryption, ts)?; let key = public_key_material_to_key(&dec, KeyType::Decryption, ts)?;
@ -297,7 +294,7 @@ pub fn test_get_pub(
// -- // --
let auth = card_client.public_key(KeyType::Authentication)?; let auth = card_tx.public_key(KeyType::Authentication)?;
let ts = key_gen.authentication().unwrap().get().into(); let ts = key_gen.authentication().unwrap().get().into();
let key = public_key_material_to_key(&auth, KeyType::Authentication, ts)?; let key = public_key_material_to_key(&auth, KeyType::Authentication, ts)?;
@ -312,10 +309,10 @@ pub fn test_get_pub(
} }
pub fn test_reset( pub fn test_reset(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let _res = card_client.factory_reset()?; let _res = card_tx.factory_reset()?;
Ok(vec![]) Ok(vec![])
} }
@ -325,25 +322,25 @@ pub fn test_reset(
/// Returns an empty TestOutput, throws errors for unexpected Status codes /// Returns an empty TestOutput, throws errors for unexpected Status codes
/// and for unequal field values. /// and for unequal field values.
pub fn test_set_user_data( pub fn test_set_user_data(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
// name // name
card_client.set_name(b"Bar<<Foo")?; card_tx.set_name(b"Bar<<Foo")?;
// lang // lang
card_client.set_lang(&[['d', 'e'].into(), ['e', 'n'].into()])?; card_tx.set_lang(&[['d', 'e'].into(), ['e', 'n'].into()])?;
// sex // sex
card_client.set_sex(Sex::Female)?; card_tx.set_sex(Sex::Female)?;
// url // url
card_client.set_url(b"https://duckduckgo.com/")?; card_tx.set_url(b"https://duckduckgo.com/")?;
// read all the fields back again, expect equal data // read all the fields back again, expect equal data
let ch = card_client.cardholder_related_data()?; let ch = card_tx.cardholder_related_data()?;
assert_eq!(ch.name().as_deref(), Some("Bar<<Foo".as_bytes())); assert_eq!(ch.name().as_deref(), Some("Bar<<Foo".as_bytes()));
assert_eq!( assert_eq!(
@ -352,54 +349,54 @@ pub fn test_set_user_data(
); );
assert_eq!(ch.sex(), Some(Sex::Female)); assert_eq!(ch.sex(), Some(Sex::Female));
let url = card_client.url()?; let url = card_tx.url()?;
assert_eq!(&url, b"https://duckduckgo.com/"); assert_eq!(&url, b"https://duckduckgo.com/");
Ok(vec![]) Ok(vec![])
} }
pub fn test_private_data( pub fn test_private_data(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let out = vec![]; let out = vec![];
println!(); println!();
let d = card_client.private_use_do(1)?; let d = card_tx.private_use_do(1)?;
println!("data 1 {:?}", d); println!("data 1 {:?}", d);
card_client.verify_pw1("123456")?; card_tx.verify_pw1("123456")?;
card_client.set_private_use_do(1, "Foo bar1!".as_bytes().to_vec())?; card_tx.set_private_use_do(1, "Foo bar1!".as_bytes().to_vec())?;
card_client.set_private_use_do(3, "Foo bar3!".as_bytes().to_vec())?; card_tx.set_private_use_do(3, "Foo bar3!".as_bytes().to_vec())?;
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
card_client.set_private_use_do(2, "Foo bar2!".as_bytes().to_vec())?; card_tx.set_private_use_do(2, "Foo bar2!".as_bytes().to_vec())?;
card_client.set_private_use_do(4, "Foo bar4!".as_bytes().to_vec())?; card_tx.set_private_use_do(4, "Foo bar4!".as_bytes().to_vec())?;
let d = card_client.private_use_do(1)?; let d = card_tx.private_use_do(1)?;
println!("data 1 {:?}", d); println!("data 1 {:?}", d);
let d = card_client.private_use_do(2)?; let d = card_tx.private_use_do(2)?;
println!("data 2 {:?}", d); println!("data 2 {:?}", d);
let d = card_client.private_use_do(3)?; let d = card_tx.private_use_do(3)?;
println!("data 3 {:?}", d); println!("data 3 {:?}", d);
let d = card_client.private_use_do(4)?; let d = card_tx.private_use_do(4)?;
println!("data 4 {:?}", d); println!("data 4 {:?}", d);
Ok(out) Ok(out)
} }
// pub fn test_cardholder_cert( // pub fn test_cardholder_cert(
// card_client: &mut (dyn CardClient + Send + Sync), // card_tx: &mut (dyn CardTransaction + Send + Sync),
// _param: &[&str], // _param: &[&str],
// ) -> Result<TestOutput, TestError> { // ) -> Result<TestOutput, TestError> {
// let mut out = vec![]; // let mut out = vec![];
// //
// println!(); // println!();
// //
// match card_client.cardholder_certificate() { // match card_tx.cardholder_certificate() {
// Ok(res) => { // Ok(res) => {
// out.push(TestResult::Text(format!("got cert {:x?}", res.data()))) // out.push(TestResult::Text(format!("got cert {:x?}", res.data())))
// } // }
@ -412,11 +409,11 @@ pub fn test_private_data(
// } // }
// }; // };
// //
// card_client.verify_pw3("12345678")?; // card_tx.verify_pw3("12345678")?;
// //
// let data = "Foo bar baz!".as_bytes(); // let data = "Foo bar baz!".as_bytes();
// //
// match card_client.set_cardholder_certificate(data.to_vec()) { // match card_tx.set_cardholder_certificate(data.to_vec()) {
// Ok(_resp) => out.push(TestResult::Text("set cert ok".to_string())), // Ok(_resp) => out.push(TestResult::Text("set cert ok".to_string())),
// Err(e) => { // Err(e) => {
// out.push(TestResult::Text(format!( // out.push(TestResult::Text(format!(
@ -427,7 +424,7 @@ pub fn test_private_data(
// } // }
// } // }
// //
// let res = card_client.cardholder_certificate()?; // let res = card_tx.cardholder_certificate()?;
// out.push(TestResult::Text("get cert ok".to_string())); // out.push(TestResult::Text("get cert ok".to_string()));
// //
// if res.data() != data { // if res.data() != data {
@ -440,7 +437,7 @@ pub fn test_private_data(
// //
// // try using slot 2 // // try using slot 2
// //
// match card_client.select_data(2, &[0x7F, 0x21]) { // match card_tx.select_data(2, &[0x7F, 0x21]) {
// Ok(_res) => out.push(TestResult::Text("select_data ok".to_string())), // Ok(_res) => out.push(TestResult::Text("select_data ok".to_string())),
// Err(e) => { // Err(e) => {
// out.push(TestResult::Text(format!("select_data: {:?}", e))); // out.push(TestResult::Text(format!("select_data: {:?}", e)));
@ -452,24 +449,24 @@ pub fn test_private_data(
// } // }
pub fn test_pw_status( pub fn test_pw_status(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let out = vec![]; let out = vec![];
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let mut pws = ard.pw_status_bytes()?; let mut pws = ard.pw_status_bytes()?;
println!("pws {:?}", pws); println!("pws {:?}", pws);
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
pws.set_pw1_cds_valid_once(false); pws.set_pw1_cds_valid_once(false);
pws.set_pw1_pin_block(true); pws.set_pw1_pin_block(true);
card_client.set_pw_status_bytes(&pws, false)?; card_tx.set_pw_status_bytes(&pws, false)?;
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let pws = ard.pw_status_bytes()?; let pws = ard.pw_status_bytes()?;
println!("pws {:?}", pws); println!("pws {:?}", pws);
@ -480,7 +477,7 @@ pub fn test_pw_status(
/// - verify pw3 (check) -> Status /// - verify pw3 (check) -> Status
/// - verify pw1 (check) -> Status /// - verify pw1 (check) -> Status
pub fn test_verify( pub fn test_verify(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
// Steps: // Steps:
@ -498,7 +495,7 @@ pub fn test_verify(
let mut out = vec![]; let mut out = vec![];
// try to set name without verify, assert result is not ok! // try to set name without verify, assert result is not ok!
let res = card_client.set_name("Notverified<<Hello".as_bytes()); let res = card_tx.set_name("Notverified<<Hello".as_bytes());
if let Err(Error::CardStatus(s)) = res { if let Err(Error::CardStatus(s)) = res {
assert_eq!(s, StatusBytes::SecurityStatusNotSatisfied); assert_eq!(s, StatusBytes::SecurityStatusNotSatisfied);
@ -506,9 +503,9 @@ pub fn test_verify(
panic!("Status should be 'SecurityStatusNotSatisfied'"); panic!("Status should be 'SecurityStatusNotSatisfied'");
} }
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
match card_client.check_pw3() { match card_tx.check_pw3() {
Err(Error::CardStatus(s)) => { Err(Error::CardStatus(s)) => {
// e.g. yubikey5 returns an error status! // e.g. yubikey5 returns an error status!
out.push(TestResult::Status(s)); out.push(TestResult::Status(s));
@ -519,17 +516,17 @@ pub fn test_verify(
Ok(_) => out.push(TestResult::StatusOk), Ok(_) => out.push(TestResult::StatusOk),
} }
card_client.set_name(b"Admin<<Hello")?; card_tx.set_name(b"Admin<<Hello")?;
let cardholder = card_client.cardholder_related_data()?; let cardholder = card_tx.cardholder_related_data()?;
assert_eq!( assert_eq!(
cardholder.name().as_deref(), cardholder.name().as_deref(),
Some("Admin<<Hello".as_bytes()) Some("Admin<<Hello".as_bytes())
); );
card_client.verify_pw1("123456")?; card_tx.verify_pw1("123456")?;
match card_client.check_pw3() { match card_tx.check_pw3() {
Err(Error::CardStatus(s)) => { Err(Error::CardStatus(s)) => {
// e.g. yubikey5 returns an error status! // e.g. yubikey5 returns an error status!
out.push(TestResult::Status(s)); out.push(TestResult::Status(s));
@ -540,16 +537,16 @@ pub fn test_verify(
Ok(_) => out.push(TestResult::StatusOk), Ok(_) => out.push(TestResult::StatusOk),
} }
card_client.set_name(b"There<<Hello")?; card_tx.set_name(b"There<<Hello")?;
let cardholder = card_client.cardholder_related_data()?; let cardholder = card_tx.cardholder_related_data()?;
assert_eq!(cardholder.name(), Some("There<<Hello".as_bytes())); assert_eq!(cardholder.name(), Some("There<<Hello".as_bytes()));
Ok(out) Ok(out)
} }
pub fn test_change_pw( pub fn test_change_pw(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let out = vec![]; let out = vec![];
@ -557,20 +554,20 @@ pub fn test_change_pw(
// first do admin-less pw1 on gnuk // first do admin-less pw1 on gnuk
// (NOTE: Gnuk requires a key to be loaded before allowing pw changes!) // (NOTE: Gnuk requires a key to be loaded before allowing pw changes!)
println!("change pw1"); println!("change pw1");
card_client.change_pw1("123456", "abcdef00")?; card_tx.change_pw1("123456", "abcdef00")?;
// also set admin pw, which means pw1 is now only user-pw again, on gnuk // also set admin pw, which means pw1 is now only user-pw again, on gnuk
println!("change pw3"); println!("change pw3");
// ca.change_pw3("abcdef00", "abcdefgh")?; // gnuk // ca.change_pw3("abcdef00", "abcdefgh")?; // gnuk
card_client.change_pw3("12345678", "abcdefgh")?; card_tx.change_pw3("12345678", "abcdefgh")?;
println!("change pw1"); println!("change pw1");
card_client.change_pw1("abcdef00", "abcdef")?; // gnuk card_tx.change_pw1("abcdef00", "abcdef")?; // gnuk
// ca.change_pw1("123456", "abcdef")?; // ca.change_pw1("123456", "abcdef")?;
println!("verify bad pw1"); println!("verify bad pw1");
match card_client.verify_pw1("123456ab") { match card_tx.verify_pw1("123456ab") {
Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => { Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => {
// this is expected // this is expected
} }
@ -581,10 +578,10 @@ pub fn test_change_pw(
} }
println!("verify good pw1"); println!("verify good pw1");
card_client.verify_pw1("abcdef")?; card_tx.verify_pw1("abcdef")?;
println!("verify bad pw3"); println!("verify bad pw3");
match card_client.verify_pw3("00000000") { match card_tx.verify_pw3("00000000") {
Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => { Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => {
// this is expected // this is expected
} }
@ -595,34 +592,34 @@ pub fn test_change_pw(
} }
println!("verify good pw3"); println!("verify good pw3");
card_client.verify_pw3("abcdefgh")?; card_tx.verify_pw3("abcdefgh")?;
println!("change pw3 back to default"); println!("change pw3 back to default");
card_client.change_pw3("abcdefgh", "12345678")?; card_tx.change_pw3("abcdefgh", "12345678")?;
println!("change pw1 back to default"); println!("change pw1 back to default");
card_client.change_pw1("abcdef", "123456")?; card_tx.change_pw1("abcdef", "123456")?;
Ok(out) Ok(out)
} }
pub fn test_reset_retry_counter( pub fn test_reset_retry_counter(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
_param: &[&str], _param: &[&str],
) -> Result<TestOutput, TestError> { ) -> Result<TestOutput, TestError> {
let out = vec![]; let out = vec![];
// set pw3, then pw1 (to bring gnuk into non-admin mode) // set pw3, then pw1 (to bring gnuk into non-admin mode)
println!("set pw3"); println!("set pw3");
card_client.change_pw3("12345678", "12345678")?; card_tx.change_pw3("12345678", "12345678")?;
println!("set pw1"); println!("set pw1");
card_client.change_pw1("123456", "123456")?; card_tx.change_pw1("123456", "123456")?;
println!("break pw1"); println!("break pw1");
let _ = card_client.verify_pw1("wrong0"); let _ = card_tx.verify_pw1("wrong0");
let _ = card_client.verify_pw1("wrong0"); let _ = card_tx.verify_pw1("wrong0");
let _ = card_client.verify_pw1("wrong0"); let _ = card_tx.verify_pw1("wrong0");
let res = card_client.verify_pw1("wrong0"); let res = card_tx.verify_pw1("wrong0");
match res { match res {
Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked)) => { Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked)) => {
@ -643,23 +640,23 @@ pub fn test_reset_retry_counter(
} }
println!("verify pw3"); println!("verify pw3");
card_client.verify_pw3("12345678")?; card_tx.verify_pw3("12345678")?;
println!("set resetting code"); println!("set resetting code");
card_client.set_resetting_code("abcdefgh".as_bytes().to_vec())?; card_tx.set_resetting_code("abcdefgh".as_bytes().to_vec())?;
println!("reset retry counter"); println!("reset retry counter");
// ca.reset_retry_counter_pw1("abcdef".as_bytes().to_vec(), None)?; // ca.reset_retry_counter_pw1("abcdef".as_bytes().to_vec(), None)?;
let _res = card_client.reset_retry_counter_pw1( let _res = card_tx.reset_retry_counter_pw1(
"abcdef".as_bytes().to_vec(), "abcdef".as_bytes().to_vec(),
Some("abcdefgh".as_bytes().to_vec()), Some("abcdefgh".as_bytes().to_vec()),
); );
println!("verify good pw1"); println!("verify good pw1");
card_client.verify_pw1("abcdef")?; card_tx.verify_pw1("abcdef")?;
println!("verify bad pw1"); println!("verify bad pw1");
match card_client.verify_pw1("00000000") { match card_tx.verify_pw1("00000000") {
Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => { Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied)) => {
// this is expected // this is expected
} }
@ -675,7 +672,7 @@ pub fn test_reset_retry_counter(
pub fn run_test( pub fn run_test(
tc: &mut TestCardData, tc: &mut TestCardData,
t: fn( t: fn(
&mut (dyn CardClient + Send + Sync), &mut (dyn CardTransaction + Send + Sync),
&[&str], &[&str],
) -> Result<TestOutput, TestError>, ) -> Result<TestOutput, TestError>,
param: &[&str], param: &[&str],

View file

@ -17,14 +17,14 @@ use sequoia_openpgp::serialize::stream::{
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::card_do::KeyGenerationTime; use openpgp_card::card_do::KeyGenerationTime;
use openpgp_card::{CardClient, KeyType}; use openpgp_card::{CardTransaction, KeyType};
use openpgp_card_sequoia::sq_util; use openpgp_card_sequoia::sq_util;
use openpgp_card_sequoia::util::vka_as_uploadable_key; use openpgp_card_sequoia::util::vka_as_uploadable_key;
pub const SP: &StandardPolicy = &StandardPolicy::new(); pub const SP: &StandardPolicy = &StandardPolicy::new();
pub(crate) fn upload_subkeys( pub(crate) fn upload_subkeys(
card_client: &mut dyn CardClient, card_tx: &mut dyn CardTransaction,
cert: &Cert, cert: &Cert,
policy: &dyn Policy, policy: &dyn Policy,
) -> Result<Vec<(String, KeyGenerationTime)>> { ) -> Result<Vec<(String, KeyGenerationTime)>> {
@ -49,7 +49,7 @@ pub(crate) fn upload_subkeys(
// upload key // upload key
let cuk = vka_as_uploadable_key(vka, None); let cuk = vka_as_uploadable_key(vka, None);
card_client.key_import(cuk, *kt)?; card_tx.key_import(cuk, *kt)?;
} }
} }

View file

@ -16,7 +16,7 @@ use openpgp_card::card_do::{
ExtendedCapabilities, ExtendedLengthInfo, Fingerprint, HistoricalBytes, ExtendedCapabilities, ExtendedLengthInfo, Fingerprint, HistoricalBytes,
KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex, KeyGenerationTime, Lang, PWStatusBytes, SecuritySupportTemplate, Sex,
}; };
use openpgp_card::{CardClient, Error, KeySet, KeyType, Response}; use openpgp_card::{CardTransaction, Error, KeySet, KeyType, Response};
use crate::decryptor::CardDecryptor; use crate::decryptor::CardDecryptor;
use crate::signer::CardSigner; use crate::signer::CardSigner;
@ -27,7 +27,7 @@ use openpgp_card::crypto_data::PublicKeyMaterial;
/// Representation of an opened OpenPGP card in its base state (i.e. no /// Representation of an opened OpenPGP card in its base state (i.e. no
/// passwords have been verified, default authorization applies). /// passwords have been verified, default authorization applies).
pub struct Open<'a> { pub struct Open<'a> {
card_client: &'a mut (dyn CardClient + Send + Sync), card_tx: &'a mut (dyn CardTransaction + Send + Sync),
// Cache of "application related data". // Cache of "application related data".
// //
@ -47,12 +47,12 @@ pub struct Open<'a> {
impl<'a> Open<'a> { impl<'a> Open<'a> {
pub fn new( pub fn new(
card_client: &'a mut (dyn CardClient + Send + Sync), card_tx: &'a mut (dyn CardTransaction + Send + Sync),
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
Ok(Self { Ok(Self {
card_client, card_tx,
ard, ard,
pw1: false, pw1: false,
pw1_sign: false, pw1_sign: false,
@ -60,15 +60,15 @@ impl<'a> Open<'a> {
}) })
} }
pub fn feature_pinpad_verify(&mut self) -> bool { pub fn feature_pinpad_verify(&mut self) -> bool {
self.card_client.feature_pinpad_verify() self.card_tx.feature_pinpad_verify()
} }
pub fn feature_pinpad_modify(&mut self) -> bool { pub fn feature_pinpad_modify(&mut self) -> bool {
self.card_client.feature_pinpad_modify() self.card_tx.feature_pinpad_modify()
} }
pub fn verify_user(&mut self, pin: &str) -> Result<(), Error> { pub fn verify_user(&mut self, pin: &str) -> Result<(), Error> {
let _ = self.card_client.verify_pw1(pin)?; let _ = self.card_tx.verify_pw1(pin)?;
self.pw1 = true; self.pw1 = true;
Ok(()) Ok(())
} }
@ -79,13 +79,13 @@ impl<'a> Open<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
prompt(); prompt();
let _ = self.card_client.verify_pw1_pinpad()?; let _ = self.card_tx.verify_pw1_pinpad()?;
self.pw1 = true; self.pw1 = true;
Ok(()) Ok(())
} }
pub fn verify_user_for_signing(&mut self, pin: &str) -> Result<(), Error> { pub fn verify_user_for_signing(&mut self, pin: &str) -> Result<(), Error> {
let _ = self.card_client.verify_pw1_for_signing(pin)?; let _ = self.card_tx.verify_pw1_for_signing(pin)?;
// FIXME: depending on card mode, pw1_sign is only usable once // FIXME: depending on card mode, pw1_sign is only usable once
@ -99,7 +99,7 @@ impl<'a> Open<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
prompt(); prompt();
let _ = self.card_client.verify_pw1_for_signing_pinpad()?; let _ = self.card_tx.verify_pw1_for_signing_pinpad()?;
// FIXME: depending on card mode, pw1_sign is only usable once // FIXME: depending on card mode, pw1_sign is only usable once
@ -108,7 +108,7 @@ impl<'a> Open<'a> {
} }
pub fn verify_admin(&mut self, pin: &str) -> Result<(), Error> { pub fn verify_admin(&mut self, pin: &str) -> Result<(), Error> {
let _ = self.card_client.verify_pw3(pin)?; let _ = self.card_tx.verify_pw3(pin)?;
self.pw3 = true; self.pw3 = true;
Ok(()) Ok(())
} }
@ -119,7 +119,7 @@ impl<'a> Open<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
prompt(); prompt();
let _ = self.card_client.verify_pw3_pinpad()?; let _ = self.card_tx.verify_pw3_pinpad()?;
self.pw3 = true; self.pw3 = true;
Ok(()) Ok(())
} }
@ -128,14 +128,14 @@ impl<'a> Open<'a> {
/// ///
/// NOTE: on some cards this functionality seems broken. /// NOTE: on some cards this functionality seems broken.
pub fn check_user_verified(&mut self) -> Result<Response, Error> { pub fn check_user_verified(&mut self) -> Result<Response, Error> {
self.card_client.check_pw1() self.card_tx.check_pw1()
} }
/// Ask the card if the admin password has been successfully verified. /// Ask the card if the admin password has been successfully verified.
/// ///
/// NOTE: on some cards this functionality seems broken. /// NOTE: on some cards this functionality seems broken.
pub fn check_admin_verified(&mut self) -> Result<Response, Error> { pub fn check_admin_verified(&mut self) -> Result<Response, Error> {
self.card_client.check_pw3() self.card_tx.check_pw3()
} }
pub fn change_user_pin( pub fn change_user_pin(
@ -143,7 +143,7 @@ impl<'a> Open<'a> {
old: &str, old: &str,
new: &str, new: &str,
) -> Result<Response, Error> { ) -> Result<Response, Error> {
self.card_client.change_pw1(old, new) self.card_tx.change_pw1(old, new)
} }
pub fn change_user_pin_pinpad( pub fn change_user_pin_pinpad(
@ -151,7 +151,7 @@ impl<'a> Open<'a> {
prompt: &dyn Fn(), prompt: &dyn Fn(),
) -> Result<Response, Error> { ) -> Result<Response, Error> {
prompt(); prompt();
self.card_client.change_pw1_pinpad() self.card_tx.change_pw1_pinpad()
} }
pub fn reset_user_pin( pub fn reset_user_pin(
@ -159,7 +159,7 @@ impl<'a> Open<'a> {
rst: &str, rst: &str,
new: &str, new: &str,
) -> Result<Response, Error> { ) -> Result<Response, Error> {
self.card_client self.card_tx
.reset_retry_counter_pw1(new.into(), Some(rst.into())) .reset_retry_counter_pw1(new.into(), Some(rst.into()))
} }
@ -168,7 +168,7 @@ impl<'a> Open<'a> {
old: &str, old: &str,
new: &str, new: &str,
) -> Result<Response, Error> { ) -> Result<Response, Error> {
self.card_client.change_pw3(old, new) self.card_tx.change_pw3(old, new)
} }
pub fn change_admin_pin_pinpad( pub fn change_admin_pin_pinpad(
@ -176,7 +176,7 @@ impl<'a> Open<'a> {
prompt: &dyn Fn(), prompt: &dyn Fn(),
) -> Result<Response, Error> { ) -> Result<Response, Error> {
prompt(); prompt();
self.card_client.change_pw3_pinpad() self.card_tx.change_pw3_pinpad()
} }
/// Get a view of the card authenticated for "User" commands. /// Get a view of the card authenticated for "User" commands.
@ -296,21 +296,21 @@ impl<'a> Open<'a> {
// --- URL (5f50) --- // --- URL (5f50) ---
pub fn url(&mut self) -> Result<String> { pub fn url(&mut self) -> Result<String> {
Ok(String::from_utf8_lossy(&self.card_client.url()?).to_string()) Ok(String::from_utf8_lossy(&self.card_tx.url()?).to_string())
} }
// --- cardholder related data (65) --- // --- cardholder related data (65) ---
pub fn cardholder_related_data( pub fn cardholder_related_data(
&mut self, &mut self,
) -> Result<CardholderRelatedData> { ) -> Result<CardholderRelatedData> {
self.card_client.cardholder_related_data() self.card_tx.cardholder_related_data()
} }
// --- security support template (7a) --- // --- security support template (7a) ---
pub fn security_support_template( pub fn security_support_template(
&mut self, &mut self,
) -> Result<SecuritySupportTemplate> { ) -> Result<SecuritySupportTemplate> {
self.card_client.security_support_template() self.card_tx.security_support_template()
} }
// DO "Algorithm Information" (0xFA) // DO "Algorithm Information" (0xFA)
@ -324,12 +324,12 @@ impl<'a> Open<'a> {
return Ok(None); return Ok(None);
} }
self.card_client.algorithm_information() self.card_tx.algorithm_information()
} }
/// Firmware Version, YubiKey specific (?) /// Firmware Version, YubiKey specific (?)
pub fn firmware_version(&mut self) -> Result<Vec<u8>> { pub fn firmware_version(&mut self) -> Result<Vec<u8>> {
self.card_client.firmware_version() self.card_tx.firmware_version()
} }
// ---------- // ----------
@ -338,14 +338,14 @@ impl<'a> Open<'a> {
&mut self, &mut self,
key_type: KeyType, key_type: KeyType,
) -> Result<PublicKeyMaterial> { ) -> Result<PublicKeyMaterial> {
self.card_client.public_key(key_type).map_err(|e| e.into()) self.card_tx.public_key(key_type).map_err(|e| e.into())
} }
// ---------- // ----------
/// Delete all state on this OpenPGP card /// Delete all state on this OpenPGP card
pub fn factory_reset(&mut self) -> Result<()> { pub fn factory_reset(&mut self) -> Result<()> {
self.card_client.factory_reset() self.card_tx.factory_reset()
} }
} }
@ -357,7 +357,7 @@ pub struct User<'app, 'open> {
impl User<'_, '_> { impl User<'_, '_> {
pub fn decryptor(&mut self, cert: &Cert) -> Result<CardDecryptor, Error> { pub fn decryptor(&mut self, cert: &Cert) -> Result<CardDecryptor, Error> {
CardDecryptor::new(self.oc.card_client, cert) CardDecryptor::new(self.oc.card_tx, cert)
} }
} }
@ -375,14 +375,14 @@ impl Sign<'_, '_> {
// FIXME: depending on the setting in "PW1 Status byte", only one // FIXME: depending on the setting in "PW1 Status byte", only one
// signature can be made after verification for signing // signature can be made after verification for signing
CardSigner::new(self.oc.card_client, cert) CardSigner::new(self.oc.card_tx, cert)
} }
pub fn signer_from_pubkey(&mut self, pubkey: PublicKey) -> CardSigner { pub fn signer_from_pubkey(&mut self, pubkey: PublicKey) -> CardSigner {
// FIXME: depending on the setting in "PW1 Status byte", only one // FIXME: depending on the setting in "PW1 Status byte", only one
// signature can be made after verification for signing // signature can be made after verification for signing
CardSigner::with_pubkey(self.oc.card_client, pubkey) CardSigner::with_pubkey(self.oc.card_tx, pubkey)
} }
} }
@ -408,7 +408,7 @@ impl Admin<'_, '_> {
return Err(anyhow!("Invalid char in name").into()); return Err(anyhow!("Invalid char in name").into());
}; };
self.oc.card_client.set_name(name.as_bytes()) self.oc.card_tx.set_name(name.as_bytes())
} }
pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> { pub fn set_lang(&mut self, lang: &[Lang]) -> Result<Response, Error> {
@ -416,11 +416,11 @@ impl Admin<'_, '_> {
return Err(anyhow!("lang too long").into()); return Err(anyhow!("lang too long").into());
} }
self.oc.card_client.set_lang(lang) self.oc.card_tx.set_lang(lang)
} }
pub fn set_sex(&mut self, sex: Sex) -> Result<Response, Error> { pub fn set_sex(&mut self, sex: Sex) -> Result<Response, Error> {
self.oc.card_client.set_sex(sex) self.oc.card_tx.set_sex(sex)
} }
pub fn set_url(&mut self, url: &str) -> Result<Response, Error> { pub fn set_url(&mut self, url: &str) -> Result<Response, Error> {
@ -438,7 +438,7 @@ impl Admin<'_, '_> {
// or if it's within the acceptable length: // or if it's within the acceptable length:
// send the url update to the card. // send the url update to the card.
self.oc.card_client.set_url(url.as_bytes()) self.oc.card_tx.set_url(url.as_bytes())
} else { } else {
Err(anyhow!("URL too long").into()) Err(anyhow!("URL too long").into())
} }
@ -448,13 +448,11 @@ impl Admin<'_, '_> {
&mut self, &mut self,
pin: &str, pin: &str,
) -> Result<Response, Error> { ) -> Result<Response, Error> {
self.oc.card_client.set_resetting_code(pin.into()) self.oc.card_tx.set_resetting_code(pin.into())
} }
pub fn reset_user_pin(&mut self, new: &str) -> Result<Response, Error> { pub fn reset_user_pin(&mut self, new: &str) -> Result<Response, Error> {
self.oc self.oc.card_tx.reset_retry_counter_pw1(new.into(), None)
.card_client
.reset_retry_counter_pw1(new.into(), None)
} }
/// Upload a ValidErasedKeyAmalgamation to the card as a specific KeyType. /// Upload a ValidErasedKeyAmalgamation to the card as a specific KeyType.
@ -467,7 +465,7 @@ impl Admin<'_, '_> {
password: Option<String>, password: Option<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let key = vka_as_uploadable_key(vka, password); let key = vka_as_uploadable_key(vka, password);
self.oc.card_client.key_import(key, key_type) self.oc.card_tx.key_import(key, key_type)
} }
pub fn generate_key_simple( pub fn generate_key_simple(
@ -476,12 +474,12 @@ impl Admin<'_, '_> {
algo: Option<AlgoSimple>, algo: Option<AlgoSimple>,
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> { ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
match algo { match algo {
Some(algo) => self.oc.card_client.generate_key_simple( Some(algo) => self.oc.card_tx.generate_key_simple(
public_to_fingerprint, public_to_fingerprint,
key_type, key_type,
algo, algo,
), ),
None => self.oc.card_client.generate_key( None => self.oc.card_tx.generate_key(
public_to_fingerprint, public_to_fingerprint,
key_type, key_type,
None, None,

View file

@ -15,14 +15,14 @@ use openpgp::Cert;
use sequoia_openpgp as openpgp; use sequoia_openpgp as openpgp;
use openpgp_card::crypto_data::Cryptogram; use openpgp_card::crypto_data::Cryptogram;
use openpgp_card::{CardClient, Error}; use openpgp_card::{CardTransaction, Error};
use crate::sq_util; use crate::sq_util;
use crate::PublicKey; use crate::PublicKey;
pub struct CardDecryptor<'a> { pub struct CardDecryptor<'a> {
/// The OpenPGP card (authenticated to allow decryption operations) /// The OpenPGP card (authenticated to allow decryption operations)
card_client: &'a mut dyn CardClient, card_tx: &'a mut dyn CardTransaction,
/// The matching public key for the card's decryption key /// The matching public key for the card's decryption key
public: PublicKey, public: PublicKey,
@ -34,11 +34,11 @@ impl<'a> CardDecryptor<'a> {
/// An Error is returned if no match between the card's decryption /// An Error is returned if no match between the card's decryption
/// key and a (sub)key of `cert` can be made. /// key and a (sub)key of `cert` can be made.
pub fn new( pub fn new(
card_client: &'a mut dyn CardClient, card_tx: &'a mut dyn CardTransaction,
cert: &Cert, cert: &Cert,
) -> Result<CardDecryptor<'a>, Error> { ) -> Result<CardDecryptor<'a>, Error> {
// Get the fingerprint for the decryption key from the card. // Get the fingerprint for the decryption key from the card.
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let fps = ard.fingerprints()?; let fps = ard.fingerprints()?;
let fp = fps.decryption(); let fp = fps.decryption();
@ -48,10 +48,7 @@ impl<'a> CardDecryptor<'a> {
if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? { if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? {
let public = eka.key().clone(); let public = eka.key().clone();
Ok(Self { Ok(Self { card_tx, public })
card_client,
public,
})
} else { } else {
Err(Error::InternalError(anyhow!( Err(Error::InternalError(anyhow!(
"Failed to find (sub)key {} in cert", "Failed to find (sub)key {} in cert",
@ -85,7 +82,7 @@ impl<'a> crypto::Decryptor for CardDecryptor<'a> {
match (ciphertext, self.public.mpis()) { match (ciphertext, self.public.mpis()) {
(mpi::Ciphertext::RSA { c: ct }, mpi::PublicKey::RSA { .. }) => { (mpi::Ciphertext::RSA { c: ct }, mpi::PublicKey::RSA { .. }) => {
let dm = Cryptogram::RSA(ct.value()); let dm = Cryptogram::RSA(ct.value());
let dec = self.card_client.decipher(dm)?; let dec = self.card_tx.decipher(dm)?;
let sk = openpgp::crypto::SessionKey::from(&dec[..]); let sk = openpgp::crypto::SessionKey::from(&dec[..]);
Ok(sk) Ok(sk)
@ -109,7 +106,7 @@ impl<'a> crypto::Decryptor for CardDecryptor<'a> {
}; };
// Decryption operation on the card // Decryption operation on the card
let mut dec = self.card_client.decipher(dm)?; let mut dec = self.card_tx.decipher(dm)?;
// Specifically handle return value format like Gnuk's // Specifically handle return value format like Gnuk's
// (Gnuk returns a leading '0x04' byte and // (Gnuk returns a leading '0x04' byte and

View file

@ -11,14 +11,14 @@ use openpgp::types::{Curve, PublicKeyAlgorithm};
use sequoia_openpgp as openpgp; use sequoia_openpgp as openpgp;
use openpgp_card::crypto_data::Hash; use openpgp_card::crypto_data::Hash;
use openpgp_card::{CardClient, Error}; use openpgp_card::{CardTransaction, Error};
use crate::sq_util; use crate::sq_util;
use crate::PublicKey; use crate::PublicKey;
pub struct CardSigner<'a> { pub struct CardSigner<'a> {
/// The OpenPGP card (authenticated to allow signing operations) /// The OpenPGP card (authenticated to allow signing operations)
card_client: &'a mut (dyn CardClient + Send + Sync), card_tx: &'a mut (dyn CardTransaction + Send + Sync),
/// The matching public key for the card's signing key /// The matching public key for the card's signing key
public: PublicKey, public: PublicKey,
@ -30,11 +30,11 @@ impl<'a> CardSigner<'a> {
/// An Error is returned if no match between the card's signing /// An Error is returned if no match between the card's signing
/// key and a (sub)key of `cert` can be made. /// key and a (sub)key of `cert` can be made.
pub fn new( pub fn new(
card_client: &'a mut (dyn CardClient + Send + Sync), card_tx: &'a mut (dyn CardTransaction + Send + Sync),
cert: &openpgp::Cert, cert: &openpgp::Cert,
) -> Result<CardSigner<'a>, Error> { ) -> Result<CardSigner<'a>, Error> {
// Get the fingerprint for the signing key from the card. // Get the fingerprint for the signing key from the card.
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let fps = ard.fingerprints()?; let fps = ard.fingerprints()?;
let fp = fps.signature(); let fp = fps.signature();
@ -44,7 +44,7 @@ impl<'a> CardSigner<'a> {
if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? { if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? {
let key = eka.key().clone(); let key = eka.key().clone();
Ok(Self::with_pubkey(card_client, key)) Ok(Self::with_pubkey(card_tx, key))
} else { } else {
Err(Error::InternalError(anyhow!( Err(Error::InternalError(anyhow!(
"Failed to find (sub)key {} in cert", "Failed to find (sub)key {} in cert",
@ -59,13 +59,10 @@ impl<'a> CardSigner<'a> {
} }
pub(crate) fn with_pubkey( pub(crate) fn with_pubkey(
card_client: &'a mut (dyn CardClient + Send + Sync), card_tx: &'a mut (dyn CardTransaction + Send + Sync),
public: PublicKey, public: PublicKey,
) -> CardSigner<'a> { ) -> CardSigner<'a> {
CardSigner { CardSigner { card_tx, public }
card_client,
public,
}
} }
} }
@ -117,7 +114,7 @@ impl<'a> crypto::Signer for CardSigner<'a> {
} }
}; };
let sig = self.card_client.signature_for_hash(hash)?; let sig = self.card_tx.signature_for_hash(hash)?;
let mpi = mpi::MPI::new(&sig[..]); let mpi = mpi::MPI::new(&sig[..]);
Ok(mpi::Signature::RSA { s: mpi }) Ok(mpi::Signature::RSA { s: mpi })
@ -125,7 +122,7 @@ impl<'a> crypto::Signer for CardSigner<'a> {
(PublicKeyAlgorithm::EdDSA, mpi::PublicKey::EdDSA { .. }) => { (PublicKeyAlgorithm::EdDSA, mpi::PublicKey::EdDSA { .. }) => {
let hash = Hash::EdDSA(digest); let hash = Hash::EdDSA(digest);
let sig = self.card_client.signature_for_hash(hash)?; let sig = self.card_tx.signature_for_hash(hash)?;
let r = mpi::MPI::new(&sig[..32]); let r = mpi::MPI::new(&sig[..32]);
let s = mpi::MPI::new(&sig[32..]); let s = mpi::MPI::new(&sig[32..]);
@ -143,7 +140,7 @@ impl<'a> crypto::Signer for CardSigner<'a> {
_ => Hash::ECDSA(digest), _ => Hash::ECDSA(digest),
}; };
let sig = self.card_client.signature_for_hash(hash)?; let sig = self.card_tx.signature_for_hash(hash)?;
let len_2 = sig.len() / 2; let len_2 = sig.len() / 2;
let r = mpi::MPI::new(&sig[..len_2]); let r = mpi::MPI::new(&sig[..len_2]);

View file

@ -27,7 +27,7 @@ use sequoia_openpgp as openpgp;
use openpgp_card::algorithm::{Algo, Curve}; use openpgp_card::algorithm::{Algo, Curve};
use openpgp_card::card_do::{Fingerprint, KeyGenerationTime}; use openpgp_card::card_do::{Fingerprint, KeyGenerationTime};
use openpgp_card::crypto_data::{CardUploadableKey, PublicKeyMaterial}; use openpgp_card::crypto_data::{CardUploadableKey, PublicKeyMaterial};
use openpgp_card::{CardClient, Error, KeyType}; use openpgp_card::{CardTransaction, Error, KeyType};
use crate::card::Open; use crate::card::Open;
use crate::privkey::SequoiaKey; use crate::privkey::SequoiaKey;
@ -294,13 +294,13 @@ pub fn vka_as_uploadable_key(
/// FIXME: this fn is used in card_functionality, but should be removed /// FIXME: this fn is used in card_functionality, but should be removed
pub fn sign( pub fn sign(
card_client: &mut (dyn CardClient + Send + Sync), card_tx: &mut (dyn CardTransaction + Send + Sync),
cert: &Cert, cert: &Cert,
input: &mut dyn io::Read, input: &mut dyn io::Read,
) -> Result<String> { ) -> Result<String> {
let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?; let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?;
{ {
let s = signer::CardSigner::new(card_client, cert)?; let s = signer::CardSigner::new(card_tx, cert)?;
let message = Message::new(&mut armorer); let message = Message::new(&mut armorer);
let mut message = Signer::new(message, s).detached().build()?; let mut message = Signer::new(message, s).detached().build()?;
@ -318,7 +318,7 @@ pub fn sign(
/// FIXME: this fn is used in card_functionality, but should be removed /// FIXME: this fn is used in card_functionality, but should be removed
pub fn decrypt( pub fn decrypt(
card_client: &mut dyn CardClient, card_tx: &mut dyn CardTransaction,
cert: &Cert, cert: &Cert,
msg: Vec<u8>, msg: Vec<u8>,
p: &dyn Policy, p: &dyn Policy,
@ -327,7 +327,7 @@ pub fn decrypt(
{ {
let reader = io::BufReader::new(&msg[..]); let reader = io::BufReader::new(&msg[..]);
let d = decryptor::CardDecryptor::new(card_client, cert)?; let d = decryptor::CardDecryptor::new(card_tx, cert)?;
let db = DecryptorBuilder::from_reader(reader)?; let db = DecryptorBuilder::from_reader(reader)?;
let mut decryptor = db.with_policy(p, None, d)?; let mut decryptor = db.with_policy(p, None, d)?;

View file

@ -13,7 +13,7 @@ use std::convert::TryFrom;
use crate::apdu::command::Expect; use crate::apdu::command::Expect;
use crate::apdu::{command::Command, response::RawResponse}; use crate::apdu::{command::Command, response::RawResponse};
use crate::{CardClient, Error, StatusBytes}; use crate::{CardTransaction, Error, StatusBytes};
/// "Maximum amount of bytes in a short APDU command or response" (from pcsc) /// "Maximum amount of bytes in a short APDU command or response" (from pcsc)
const MAX_BUFFER_SIZE: usize = 264; const MAX_BUFFER_SIZE: usize = 264;
@ -23,15 +23,15 @@ const MAX_BUFFER_SIZE: usize = 264;
/// If the reply is truncated, this fn assembles all the parts and returns /// If the reply is truncated, this fn assembles all the parts and returns
/// them as one aggregated Response. /// them as one aggregated Response.
pub(crate) fn send_command<C: ?Sized>( pub(crate) fn send_command<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
cmd: Command, cmd: Command,
expect_reply: bool, expect_reply: bool,
) -> Result<RawResponse, Error> ) -> Result<RawResponse, Error>
where where
C: CardClient, C: CardTransaction,
{ {
let mut resp = RawResponse::try_from(send_command_low_level( let mut resp = RawResponse::try_from(send_command_low_level(
card_client, card_tx,
cmd.clone(), cmd.clone(),
if expect_reply { if expect_reply {
Expect::Some Expect::Some
@ -42,7 +42,7 @@ where
if let StatusBytes::UnknownStatus(0x6c, size) = resp.status() { if let StatusBytes::UnknownStatus(0x6c, size) = resp.status() {
resp = RawResponse::try_from(send_command_low_level( resp = RawResponse::try_from(send_command_low_level(
card_client, card_tx,
cmd, cmd,
Expect::Short(size), Expect::Short(size),
)?)?; )?)?;
@ -54,7 +54,7 @@ where
// Get next chunk of data // Get next chunk of data
let next = RawResponse::try_from(send_command_low_level( let next = RawResponse::try_from(send_command_low_level(
card_client, card_tx,
commands::get_response(), commands::get_response(),
Expect::Short(bytes), Expect::Short(bytes),
)?)?; )?)?;
@ -85,15 +85,15 @@ where
/// If the response is chained, this fn only returns one chunk, the caller /// If the response is chained, this fn only returns one chunk, the caller
/// needs to re-assemble the chained response-parts. /// needs to re-assemble the chained response-parts.
fn send_command_low_level<C: ?Sized>( fn send_command_low_level<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
cmd: Command, cmd: Command,
expect_response: Expect, expect_response: Expect,
) -> Result<Vec<u8>, Error> ) -> Result<Vec<u8>, Error>
where where
C: CardClient, C: CardTransaction,
{ {
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) = let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
if let Some(caps) = card_client.card_caps() { if let Some(caps) = card_tx.card_caps() {
log::debug!("found card caps data!"); log::debug!("found card caps data!");
( (
@ -109,13 +109,13 @@ where
(false, false, 255, 255) (false, false, 255, 255)
}; };
// If the CardClient implementation has an inherent limit for the cmd // If the CardTransaction implementation has an inherent limit for the cmd
// size, take that limit into account. // size, take that limit into account.
// (E.g. when using scdaemon as a CardClient backend, there is a // (E.g. when using scdaemon as a CardTransaction backend, there is a
// limitation to 1000 bytes length for Assuan commands, which // limitation to 1000 bytes length for Assuan commands, which
// translates to maximum command length of a bit under 500 bytes) // translates to maximum command length of a bit under 500 bytes)
if let Some(max_cardclient_cmd_bytes) = card_client.max_cmd_len() { if let Some(max_card_cmd_bytes) = card_tx.max_cmd_len() {
max_cmd_bytes = usize::min(max_cmd_bytes, max_cardclient_cmd_bytes); max_cmd_bytes = usize::min(max_cmd_bytes, max_card_cmd_bytes);
} }
log::debug!( log::debug!(
@ -167,7 +167,7 @@ where
log::debug!(" -> chained APDU command: {:x?}", &serialized); log::debug!(" -> chained APDU command: {:x?}", &serialized);
let resp = card_client.transmit(&serialized, buf_size)?; let resp = card_tx.transmit(&serialized, buf_size)?;
log::debug!(" <- APDU response: {:x?}", &resp); log::debug!(" <- APDU response: {:x?}", &resp);
@ -210,7 +210,7 @@ where
log::debug!(" -> APDU command: {:x?}", &serialized); log::debug!(" -> APDU command: {:x?}", &serialized);
let resp = card_client.transmit(&serialized, buf_size)?; let resp = card_tx.transmit(&serialized, buf_size)?;
log::debug!(" <- APDU response: {:x?}", resp); log::debug!(" <- APDU response: {:x?}", resp);

View file

@ -17,7 +17,7 @@ use crate::crypto_data::{
}; };
use crate::tlv::{length::tlv_encode_length, value::Value, Tlv}; use crate::tlv::{length::tlv_encode_length, value::Value, Tlv};
use crate::{apdu, KeyType}; use crate::{apdu, KeyType};
use crate::{CardClient, Error}; use crate::{CardTransaction, Error};
/// Generate asymmetric key pair on the card. /// Generate asymmetric key pair on the card.
/// ///
@ -30,7 +30,7 @@ use crate::{CardClient, Error};
/// `fp_from_pub` calculates the fingerprint for a public key data object and /// `fp_from_pub` calculates the fingerprint for a public key data object and
/// creation timestamp /// creation timestamp
pub(crate) fn gen_key_with_metadata<C: ?Sized>( pub(crate) fn gen_key_with_metadata<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
fp_from_pub: fn( fp_from_pub: fn(
&PublicKeyMaterial, &PublicKeyMaterial,
KeyGenerationTime, KeyGenerationTime,
@ -40,17 +40,17 @@ pub(crate) fn gen_key_with_metadata<C: ?Sized>(
algo: Option<&Algo>, algo: Option<&Algo>,
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error>
where where
C: CardClient, C: CardTransaction,
{ {
// Set algo on card if it's Some // Set algo on card if it's Some
if let Some(target_algo) = algo { if let Some(target_algo) = algo {
// FIXME: caching // FIXME: caching
let ard = card_client.application_related_data()?; // no caching, here! let ard = card_tx.application_related_data()?; // no caching, here!
let ecap = ard.extended_capabilities()?; let ecap = ard.extended_capabilities()?;
// Only set algo if card supports setting of algo attr // Only set algo if card supports setting of algo attr
if ecap.algo_attrs_changeable() { if ecap.algo_attrs_changeable() {
card_client.set_algorithm_attributes(key_type, target_algo)?; card_tx.set_algorithm_attributes(key_type, target_algo)?;
} else { } else {
// Check if the current algo on the card is the one we want, if // Check if the current algo on the card is the one we want, if
// not we return an error. // not we return an error.
@ -67,11 +67,11 @@ where
} }
// get current (possibly updated) state of algo // get current (possibly updated) state of algo
let ard = card_client.application_related_data()?; // no caching, here! let ard = card_tx.application_related_data()?; // no caching, here!
let cur_algo = ard.algorithm_attributes(key_type)?; let cur_algo = ard.algorithm_attributes(key_type)?;
// generate key // generate key
let tlv = generate_asymmetric_key_pair(card_client, key_type)?; let tlv = generate_asymmetric_key_pair(card_tx, key_type)?;
// derive pubkey // derive pubkey
let pubkey = tlv_to_pubkey(&tlv, &cur_algo)?; let pubkey = tlv_to_pubkey(&tlv, &cur_algo)?;
@ -89,11 +89,11 @@ where
let ts = ts.into(); let ts = ts.into();
card_client.set_creation_time(ts, key_type)?; card_tx.set_creation_time(ts, key_type)?;
// calculate/store fingerprint // calculate/store fingerprint
let fp = fp_from_pub(&pubkey, ts, key_type)?; let fp = fp_from_pub(&pubkey, ts, key_type)?;
card_client.set_fingerprint(fp, key_type)?; card_tx.set_fingerprint(fp, key_type)?;
Ok((pubkey, ts)) Ok((pubkey, ts))
} }
@ -130,17 +130,17 @@ fn tlv_to_pubkey(tlv: &Tlv, algo: &Algo) -> Result<PublicKeyMaterial> {
/// This runs the low level key generation primitive on the card. /// This runs the low level key generation primitive on the card.
/// (This does not set algorithm attributes, creation time or fingerprint) /// (This does not set algorithm attributes, creation time or fingerprint)
pub(crate) fn generate_asymmetric_key_pair<C: ?Sized>( pub(crate) fn generate_asymmetric_key_pair<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
key_type: KeyType, key_type: KeyType,
) -> Result<Tlv, Error> ) -> Result<Tlv, Error>
where where
C: CardClient, C: CardTransaction,
{ {
// generate key // generate key
let crt = control_reference_template(key_type)?; let crt = control_reference_template(key_type)?;
let gen_key_cmd = commands::gen_key(crt.serialize().to_vec()); let gen_key_cmd = commands::gen_key(crt.serialize().to_vec());
let resp = apdu::send_command(card_client, gen_key_cmd, true)?; let resp = apdu::send_command(card_tx, gen_key_cmd, true)?;
resp.check_ok()?; resp.check_ok()?;
let tlv = Tlv::try_from(resp.data()?)?; let tlv = Tlv::try_from(resp.data()?)?;
@ -155,21 +155,21 @@ where
/// ///
/// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR) /// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR)
pub(crate) fn public_key<C: ?Sized>( pub(crate) fn public_key<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
key_type: KeyType, key_type: KeyType,
) -> Result<PublicKeyMaterial, Error> ) -> Result<PublicKeyMaterial, Error>
where where
C: CardClient, C: CardTransaction,
{ {
// get current algo // get current algo
let ard = card_client.application_related_data()?; // FIXME: caching let ard = card_tx.application_related_data()?; // FIXME: caching
let algo = ard.algorithm_attributes(key_type)?; let algo = ard.algorithm_attributes(key_type)?;
// get public key // get public key
let crt = control_reference_template(key_type)?; let crt = control_reference_template(key_type)?;
let get_pub_key_cmd = commands::get_pub_key(crt.serialize().to_vec()); let get_pub_key_cmd = commands::get_pub_key(crt.serialize().to_vec());
let resp = apdu::send_command(card_client, get_pub_key_cmd, true)?; let resp = apdu::send_command(card_tx, get_pub_key_cmd, true)?;
resp.check_ok()?; resp.check_ok()?;
let tlv = Tlv::try_from(resp.data()?)?; let tlv = Tlv::try_from(resp.data()?)?;
@ -184,16 +184,16 @@ where
/// caused by checks before attempting to upload the key to the card, or by /// caused by checks before attempting to upload the key to the card, or by
/// an error that the card reports during an attempt to upload the key). /// an error that the card reports during an attempt to upload the key).
pub(crate) fn key_import<C: ?Sized>( pub(crate) fn key_import<C: ?Sized>(
card_client: &mut C, card_tx: &mut C,
key: Box<dyn CardUploadableKey>, key: Box<dyn CardUploadableKey>,
key_type: KeyType, key_type: KeyType,
algo_info: Option<AlgoInfo>, algo_info: Option<AlgoInfo>,
) -> Result<(), Error> ) -> Result<(), Error>
where where
C: CardClient, C: CardTransaction,
{ {
// FIXME: caching? // FIXME: caching?
let ard = card_client.application_related_data()?; let ard = card_tx.application_related_data()?;
let (algo, key_cmd) = match key.private_key()? { let (algo, key_cmd) = match key.private_key()? {
PrivateKeyMaterial::R(rsa_key) => { PrivateKeyMaterial::R(rsa_key) => {
@ -229,12 +229,12 @@ where
// Only set algo attrs if "Extended Capabilities" lists the feature // Only set algo attrs if "Extended Capabilities" lists the feature
if ard.extended_capabilities()?.algo_attrs_changeable() { if ard.extended_capabilities()?.algo_attrs_changeable() {
card_client.set_algorithm_attributes(key_type, &algo)?; card_tx.set_algorithm_attributes(key_type, &algo)?;
} }
apdu::send_command(card_client, key_cmd, false)?.check_ok()?; apdu::send_command(card_tx, key_cmd, false)?.check_ok()?;
card_client.set_fingerprint(fp, key_type)?; card_tx.set_fingerprint(fp, key_type)?;
card_client.set_creation_time(key.timestamp(), key_type)?; card_tx.set_creation_time(key.timestamp(), key_type)?;
Ok(()) Ok(())
} }

View file

@ -13,8 +13,8 @@
//! [OpenPGP implementation](https://www.openpgp.org/software/developer/). //! [OpenPGP implementation](https://www.openpgp.org/software/developer/).
//! //!
//! This library can't directly access cards by itself. Instead, users //! This library can't directly access cards by itself. Instead, users
//! need to supply an implementation of the [`CardClient`] trait, to //! need to supply an implementation of the [`CardBackend`]
//! access cards. //! / [`CardTransaction`] traits, to access cards.
//! //!
//! The companion crate //! The companion crate
//! [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc) //! [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)
@ -55,12 +55,13 @@ use crate::tlv::tag::Tag;
use crate::tlv::value::Value; use crate::tlv::value::Value;
use crate::tlv::Tlv; use crate::tlv::Tlv;
/// The CardClient trait defines communication with an OpenPGP card via a /// The CardTransaction trait defines communication with an OpenPGP card via a
/// backend implementation (e.g. the pcsc backend in the crate /// backend implementation (e.g. the pcsc backend in the crate
/// [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)). /// [openpgp-card-pcsc](https://crates.io/crates/openpgp-card-pcsc)),
/// after opening a transaction from a CardBackend.
/// ///
/// CardClient exposes low-level access to OpenPGP card functionality. /// CardTransaction exposes low-level access to OpenPGP card functionality.
pub trait CardClient { pub trait CardTransaction {
/// Transmit the command data in `cmd` to the card. /// Transmit the command data in `cmd` to the card.
/// ///
/// `buf_size` is a hint to the backend (the backend may ignore it) /// `buf_size` is a hint to the backend (the backend may ignore it)
@ -71,12 +72,12 @@ pub trait CardClient {
buf_size: usize, buf_size: usize,
) -> Result<Vec<u8>, Error>; ) -> Result<Vec<u8>, Error>;
/// Set the card capabilities in the CardClient. /// Set the card capabilities in the CardTransaction.
/// ///
/// Setting these capabilities is typically part of a bootstrapping /// Setting these capabilities is typically part of a bootstrapping
/// process: the information about the card's capabilities is typically /// process: the information about the card's capabilities is typically
/// requested from the card using the same CardClient instance, before /// requested from the card using the same CardTransaction instance,
/// the card's capabilities have been initialized. /// before the card's capabilities have been initialized.
fn init_card_caps(&mut self, caps: CardCaps); fn init_card_caps(&mut self, caps: CardCaps);
/// Request the card's capabilities /// Request the card's capabilities
@ -85,7 +86,7 @@ pub trait CardClient {
/// determine if extended length can be used) /// determine if extended length can be used)
fn card_caps(&self) -> Option<&CardCaps>; fn card_caps(&self) -> Option<&CardCaps>;
/// If a CardClient implementation introduces an additional, /// If a CardTransaction implementation introduces an additional,
/// backend-specific limit for maximum number of bytes per command, /// backend-specific limit for maximum number of bytes per command,
/// this fn can indicate that limit by returning `Some(max_cmd_len)`. /// this fn can indicate that limit by returning `Some(max_cmd_len)`.
fn max_cmd_len(&self) -> Option<usize> { fn max_cmd_len(&self) -> Option<usize> {
@ -110,7 +111,7 @@ pub trait CardClient {
apdu::send_command(self, select_openpgp, false)?.try_into() apdu::send_command(self, select_openpgp, false)?.try_into()
} }
/// Get a CardApp based on a CardClient. /// Get a CardApp based on a CardTransaction.
/// ///
/// It is expected that SELECT has already been performed on the card /// It is expected that SELECT has already been performed on the card
/// beforehand. /// beforehand.
@ -122,7 +123,7 @@ pub trait CardClient {
let ard = self.application_related_data()?; let ard = self.application_related_data()?;
// Determine chaining/extended length support from card // Determine chaining/extended length support from card
// metadata and cache this information in the CardClient // metadata and cache this information in the CardTransaction
// implementation (as a CardCaps) // implementation (as a CardCaps)
let mut ext_support = false; let mut ext_support = false;
let mut chaining_support = false; let mut chaining_support = false;
@ -877,14 +878,14 @@ pub trait CardClient {
} }
} }
impl<'a> Deref for dyn CardClient + Send + Sync + 'a { impl<'a> Deref for dyn CardTransaction + Send + Sync + 'a {
type Target = dyn CardClient + 'a; type Target = dyn CardTransaction + 'a;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self self
} }
} }
impl<'a> DerefMut for dyn CardClient + Send + Sync + 'a { impl<'a> DerefMut for dyn CardTransaction + Send + Sync + 'a {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
self self
} }

View file

@ -1,8 +1,9 @@
// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
//! This crate implements a `CardClient` backend for `openpgp-card`. It uses //! This crate implements a `CardBackend`/`CardTransaction` backend for
//! the PCSC middleware to access the OpenPGP application on smart cards. //! `openpgp-card`. It uses the PCSC middleware to access the OpenPGP
//! application on smart cards.
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use iso7816_tlv::simple::Tlv; use iso7816_tlv::simple::Tlv;
@ -11,7 +12,7 @@ use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
use openpgp_card::card_do::ApplicationRelatedData; use openpgp_card::card_do::ApplicationRelatedData;
use openpgp_card::{CardCaps, CardClient, Error, SmartcardError}; use openpgp_card::{CardCaps, CardTransaction, Error, SmartcardError};
const FEATURE_VERIFY_PIN_DIRECT: u8 = 0x06; const FEATURE_VERIFY_PIN_DIRECT: u8 = 0x06;
const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07; const FEATURE_MODIFY_PIN_DIRECT: u8 = 0x07;
@ -37,7 +38,7 @@ pub struct PcscCard {
reader_caps: HashMap<u8, Tlv>, reader_caps: HashMap<u8, Tlv>,
} }
/// An implementation of the CardClient trait that uses the PCSC lite /// An implementation of the CardTransaction trait that uses the PCSC lite
/// middleware to access the OpenPGP card application on smart cards, via a /// middleware to access the OpenPGP card application on smart cards, via a
/// PCSC "transaction". /// PCSC "transaction".
/// ///
@ -146,8 +147,8 @@ impl<'b> TxClient<'b> {
} }
/// Try to select the OpenPGP application on a card /// Try to select the OpenPGP application on a card
pub fn select(card_client: &mut TxClient) -> Result<(), Error> { pub fn select(card_tx: &mut TxClient) -> Result<(), Error> {
if <dyn CardClient>::select(card_client).is_ok() { if <dyn CardTransaction>::select(card_tx).is_ok() {
Ok(()) Ok(())
} else { } else {
Err(Error::Smartcard(SmartcardError::SelectOpenPGPCardFailed)) Err(Error::Smartcard(SmartcardError::SelectOpenPGPCardFailed))
@ -156,9 +157,9 @@ impl<'b> TxClient<'b> {
/// Get application_related_data from card /// Get application_related_data from card
fn application_related_data( fn application_related_data(
card_client: &mut TxClient, card_tx: &mut TxClient,
) -> Result<ApplicationRelatedData, Error> { ) -> Result<ApplicationRelatedData, Error> {
<dyn CardClient>::application_related_data(card_client).map_err(|e| { <dyn CardTransaction>::application_related_data(card_tx).map_err(|e| {
Error::Smartcard(SmartcardError::Error(format!( Error::Smartcard(SmartcardError::Error(format!(
"TxClient: failed to get application_related_data {:x?}", "TxClient: failed to get application_related_data {:x?}",
e e
@ -207,7 +208,7 @@ impl<'b> TxClient<'b> {
} }
} }
impl CardClient for TxClient<'_> { impl CardTransaction for TxClient<'_> {
fn transmit( fn transmit(
&mut self, &mut self,
cmd: &[u8], cmd: &[u8],
@ -656,8 +657,8 @@ impl PcscCard {
} }
} }
// Initialize CardClient (set CardCaps from ARD) // Initialize CardTransaction (set CardCaps from ARD)
<dyn CardClient>::initialize(&mut txc)?; <dyn CardTransaction>::initialize(&mut txc)?;
let cc = txc.card_caps().cloned(); let cc = txc.card_caps().cloned();

View file

@ -13,7 +13,7 @@ use sequoia_ipc::gnupg::{Agent, Context};
use std::sync::Mutex; use std::sync::Mutex;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use openpgp_card::{CardCaps, CardClient, Error}; use openpgp_card::{CardCaps, CardTransaction, Error};
lazy_static! { lazy_static! {
static ref RT: Mutex<Runtime> = static ref RT: Mutex<Runtime> =
@ -48,7 +48,7 @@ const ASSUAN_LINELENGTH: usize = 1000;
/// In particular, uploading rsa4096 keys fails via scdaemon, with such cards. /// In particular, uploading rsa4096 keys fails via scdaemon, with such cards.
const APDU_CMD_BYTES_MAX: usize = (ASSUAN_LINELENGTH - 25) / 2; const APDU_CMD_BYTES_MAX: usize = (ASSUAN_LINELENGTH - 25) / 2;
/// An implementation of the CardClient trait that uses GnuPG's scdaemon /// An implementation of the CardTransaction trait that uses GnuPG's scdaemon
/// (via GnuPG Agent) to access OpenPGP card devices. /// (via GnuPG Agent) to access OpenPGP card devices.
pub struct ScdClient { pub struct ScdClient {
agent: Agent, agent: Agent,
@ -65,7 +65,7 @@ impl ScdClient {
let mut card = ScdClient::new(agent, true)?; let mut card = ScdClient::new(agent, true)?;
card.select_card(serial)?; card.select_card(serial)?;
<dyn CardClient>::initialize(&mut card)?; <dyn CardTransaction>::initialize(&mut card)?;
Ok(card) Ok(card)
} }
@ -79,7 +79,7 @@ impl ScdClient {
pub fn open_yolo(agent: Option<Agent>) -> Result<Self, Error> { pub fn open_yolo(agent: Option<Agent>) -> Result<Self, Error> {
let mut card = ScdClient::new(agent, true)?; let mut card = ScdClient::new(agent, true)?;
<dyn CardClient>::initialize(&mut card)?; <dyn CardTransaction>::initialize(&mut card)?;
Ok(card) Ok(card)
} }
@ -199,7 +199,7 @@ impl ScdClient {
} }
} }
impl CardClient for ScdClient { impl CardTransaction for ScdClient {
fn transmit(&mut self, cmd: &[u8], _: usize) -> Result<Vec<u8>, Error> { fn transmit(&mut self, cmd: &[u8], _: usize) -> Result<Vec<u8>, Error> {
log::trace!("SCDC cmd len {}", cmd.len()); log::trace!("SCDC cmd len {}", cmd.len());

View file

@ -4,7 +4,7 @@
use anyhow::Result; use anyhow::Result;
use structopt::StructOpt; use structopt::StructOpt;
use openpgp_card::{CardClient, Error, StatusBytes}; use openpgp_card::{CardTransaction, Error, StatusBytes};
use openpgp_card_pcsc::PcscCard; use openpgp_card_pcsc::PcscCard;
use openpgp_card_sequoia::card::Open; use openpgp_card_sequoia::card::Open;

View file

@ -12,7 +12,7 @@ use sequoia_openpgp::serialize::SerializeInto;
use sequoia_openpgp::Cert; use sequoia_openpgp::Cert;
use openpgp_card::algorithm::AlgoSimple; use openpgp_card::algorithm::AlgoSimple;
use openpgp_card::{card_do::Sex, CardClient, KeyType}; use openpgp_card::{card_do::Sex, CardTransaction, KeyType};
use openpgp_card_sequoia::card::{Admin, Open}; use openpgp_card_sequoia::card::{Admin, Open};
use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key}; use openpgp_card_sequoia::util::{make_cert, public_key_material_to_key};
@ -156,7 +156,7 @@ fn set_identity(
let mut card = util::open_card(ident)?; let mut card = util::open_card(ident)?;
let mut txc = card.transaction()?; let mut txc = card.transaction()?;
<dyn CardClient>::set_identity(&mut txc, id)?; <dyn CardTransaction>::set_identity(&mut txc, id)?;
Ok(()) Ok(())
} }