From 920da0442b4630da71eb14c702392b1556d07eca Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Fri, 2 Jul 2021 14:21:50 +0200 Subject: [PATCH] Rename structs that represent different verification states of the OpenPGP card. --- openpgp-card-sequoia/src/decryptor.rs | 6 +- openpgp-card-sequoia/src/lib.rs | 12 ++-- openpgp-card-sequoia/src/main.rs | 14 ++--- openpgp-card-sequoia/src/signer.rs | 10 ++-- openpgp-card/src/apdu/mod.rs | 6 +- openpgp-card/src/key_upload.rs | 6 +- openpgp-card/src/lib.rs | 82 ++++++++++++++++----------- 7 files changed, 76 insertions(+), 60 deletions(-) diff --git a/openpgp-card-sequoia/src/decryptor.rs b/openpgp-card-sequoia/src/decryptor.rs index bebebcf..e1b4215 100644 --- a/openpgp-card-sequoia/src/decryptor.rs +++ b/openpgp-card-sequoia/src/decryptor.rs @@ -16,13 +16,13 @@ use openpgp::Cert; use sequoia_openpgp as openpgp; use openpgp_card::errors::OpenpgpCardError; -use openpgp_card::{DecryptMe, OpenPGPCardUser}; +use openpgp_card::{CardUser, DecryptMe}; use crate::PublicKey; pub(crate) struct CardDecryptor<'a> { /// The OpenPGP card (authenticated to allow decryption operations) - ocu: &'a OpenPGPCardUser, + ocu: &'a CardUser, /// The matching public key for the card's decryption key public: PublicKey, @@ -34,7 +34,7 @@ impl<'a> CardDecryptor<'a> { /// An Error is returned if no match between the card's decryption /// key and a (sub)key of `cert` can be made. pub fn new( - ocu: &'a OpenPGPCardUser, + ocu: &'a CardUser, cert: &Cert, policy: &dyn Policy, ) -> Result, OpenpgpCardError> { diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index 1f43204..f3681e1 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -21,8 +21,8 @@ use openpgp::serialize::stream::{Message, Signer}; use sequoia_openpgp as openpgp; use openpgp_card::{ - errors::OpenpgpCardError, CardUploadableKey, EccKey, EccType, KeyType, - OpenPGPCardAdmin, OpenPGPCardUser, PrivateKeyMaterial, RSAKey, + errors::OpenpgpCardError, CardAdmin, CardSign, CardUploadableKey, + CardUser, EccKey, EccType, KeyType, PrivateKeyMaterial, RSAKey, }; mod decryptor; @@ -216,7 +216,7 @@ impl EccKey for SqEccKey { /// FIXME: picking the (sub)key to upload should probably done with /// more intent. pub fn upload_from_cert_yolo( - oca: &OpenPGPCardAdmin, + oca: &CardAdmin, cert: &sequoia_openpgp::Cert, key_type: KeyType, password: Option, @@ -249,7 +249,7 @@ pub fn upload_from_cert_yolo( /// /// The caller needs to make sure that `vka` is suitable for `key_type`. pub fn upload_key( - oca: &OpenPGPCardAdmin, + oca: &CardAdmin, vka: ValidErasedKeyAmalgamation, key_type: KeyType, password: Option, @@ -260,7 +260,7 @@ pub fn upload_key( } pub fn decrypt( - ocu: &OpenPGPCardUser, + ocu: &CardUser, cert: &sequoia_openpgp::Cert, msg: Vec, ) -> Result> { @@ -282,7 +282,7 @@ pub fn decrypt( } pub fn sign( - ocu: &OpenPGPCardUser, + ocu: &CardSign, cert: &sequoia_openpgp::Cert, input: &mut dyn io::Read, ) -> Result { diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index a5d3ee6..cea025c 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -8,7 +8,7 @@ use anyhow::Result; use sequoia_openpgp::parse::Parse; use sequoia_openpgp::Cert; -use openpgp_card::{KeyType, OpenPGPCard}; +use openpgp_card::{CardBase, KeyType}; // Filename of test key and test message to use: @@ -29,7 +29,7 @@ fn main() -> Result<(), Box> { if let Ok(test_card_serial) = test_card_serial { println!("** get card"); - let oc = OpenPGPCard::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_serial(&test_card_serial)?; // card metadata @@ -127,13 +127,13 @@ fn main() -> Result<(), Box> { // Open fresh Card for decrypt // ----------------------------- - let oc = OpenPGPCard::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_serial(&test_card_serial)?; let app_id = oc.get_aid()?; // Check that we're still using the expected card assert_eq!(app_id.serial(), test_card_serial); - match oc.verify_pw1_82("123456") { + match oc.verify_pw1("123456") { Ok(oc_user) => { println!("pw1 82 verify ok"); @@ -160,10 +160,10 @@ fn main() -> Result<(), Box> { // ----------------------------- // Open fresh Card for signing // ----------------------------- - let oc = OpenPGPCard::open_by_serial(&test_card_serial)?; + let oc = CardBase::open_by_serial(&test_card_serial)?; // Sign - match oc.verify_pw1_81("123456") { + match oc.verify_pw1_for_signing("123456") { Ok(oc_user) => { println!("pw1 81 verify ok"); @@ -194,7 +194,7 @@ fn main() -> Result<(), Box> { println!("The following OpenPGP cards are connected to your system:"); - let cards = openpgp_card::OpenPGPCard::list_cards()?; + let cards = openpgp_card::CardBase::list_cards()?; for c in cards { println!(" '{}'", c.get_aid()?.serial()); } diff --git a/openpgp-card-sequoia/src/signer.rs b/openpgp-card-sequoia/src/signer.rs index 071e520..a7a7e63 100644 --- a/openpgp-card-sequoia/src/signer.rs +++ b/openpgp-card-sequoia/src/signer.rs @@ -11,14 +11,14 @@ use openpgp::types::PublicKeyAlgorithm; use sequoia_openpgp as openpgp; use openpgp_card::errors::OpenpgpCardError; +use openpgp_card::CardSign; use openpgp_card::Hash; -use openpgp_card::OpenPGPCardUser; use crate::PublicKey; pub(crate) struct CardSigner<'a> { /// The OpenPGP card (authenticated to allow signing operations) - ocu: &'a OpenPGPCardUser, + ocu: &'a CardSign, /// The matching public key for the card's signing key public: PublicKey, @@ -30,12 +30,12 @@ impl<'a> CardSigner<'a> { /// An Error is returned if no match between the card's signing /// key and a (sub)key of `cert` can be made. pub fn new( - ocu: &'a OpenPGPCardUser, + ocs: &'a CardSign, cert: &openpgp::Cert, policy: &dyn Policy, ) -> Result, OpenpgpCardError> { // Get the fingerprint for the signing key from the card. - let fps = ocu.get_fingerprints()?; + let fps = ocs.get_fingerprints()?; let fp = fps.signature(); if let Some(fp) = fp { @@ -58,7 +58,7 @@ impl<'a> CardSigner<'a> { let public = keys[0].clone(); Ok(CardSigner { - ocu, + ocu: ocs, public: public.role_as_unspecified().clone(), }) } else { diff --git a/openpgp-card/src/apdu/mod.rs b/openpgp-card/src/apdu/mod.rs index fd19942..0a03c4e 100644 --- a/openpgp-card/src/apdu/mod.rs +++ b/openpgp-card/src/apdu/mod.rs @@ -11,7 +11,7 @@ use std::convert::TryFrom; use crate::apdu::command::Command; use crate::apdu::response::Response; use crate::errors::{OcErrorStatus, OpenpgpCardError, SmartcardError}; -use crate::OpenPGPCard; +use crate::CardBase; #[derive(Clone, Copy, PartialEq)] pub(crate) enum Le { @@ -28,7 +28,7 @@ pub(crate) fn send_command( card: &Card, cmd: Command, ext: Le, - oc: Option<&OpenPGPCard>, + oc: Option<&CardBase>, ) -> Result { let mut resp = Response::try_from(send_command_low_level(&card, cmd, ext, oc)?)?; @@ -68,7 +68,7 @@ fn send_command_low_level( card: &Card, cmd: Command, ext: Le, - oc: Option<&OpenPGPCard>, + oc: Option<&CardBase>, ) -> Result, OpenpgpCardError> { log::trace!(" -> full APDU command: {:x?}", cmd); log::trace!(" serialized: {:x?}", cmd.serialize(ext)); diff --git a/openpgp-card/src/key_upload.rs b/openpgp-card/src/key_upload.rs index 3987fdf..d2f5292 100644 --- a/openpgp-card/src/key_upload.rs +++ b/openpgp-card/src/key_upload.rs @@ -12,7 +12,7 @@ use crate::parse::algo_attrs::{Algo, RsaAttrs}; use crate::parse::algo_info::AlgoInfo; use crate::tlv::{tag::Tag, Tlv, TlvEntry}; use crate::{ - tlv, CardUploadableKey, EccKey, EccType, KeyType, OpenPGPCardAdmin, + tlv, CardAdmin, CardUploadableKey, EccKey, EccType, KeyType, PrivateKeyMaterial, RSAKey, }; @@ -20,7 +20,7 @@ use crate::{ /// /// The client needs to make sure that the key is suitable for `key_type`. pub(crate) fn upload_key( - oca: &OpenPGPCardAdmin, + oca: &CardAdmin, key: Box, key_type: KeyType, ) -> Result<(), OpenpgpCardError> { @@ -369,7 +369,7 @@ fn ecc_algo_attrs_cmd( } fn copy_key_to_card( - oca: &OpenPGPCardAdmin, + oca: &CardAdmin, key_type: KeyType, ts: u64, fp: Vec, diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 3805227..874702d 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -27,6 +27,8 @@ mod key_upload; mod parse; mod tlv; +/// Container for a hash value. +/// These hash values can be signed by the card. pub enum Hash<'a> { SHA256([u8; 0x20]), SHA384([u8; 0x30]), @@ -97,6 +99,8 @@ pub trait EccKey { fn get_type(&self) -> EccType; } +/// A marker to distinguish between elliptic curve algorithms (ECDH, ECDSA, +/// EdDSA) #[derive(Clone, Copy)] pub enum EccType { ECDH, @@ -203,9 +207,9 @@ impl KeyType { } } -/// Representation of an opened OpenPGP card, with default privileges (i.e. -/// no passwords have been verified) -pub struct OpenPGPCard { +/// Representation of an opened OpenPGP card in its basic, freshly opened, +/// state (i.e. no passwords have been verified, default privileges apply). +pub struct CardBase { card: Card, // Cache of "application related data". @@ -215,7 +219,7 @@ pub struct OpenPGPCard { ard: Tlv, } -impl OpenPGPCard { +impl CardBase { /// Get all cards that can be opened as an OpenPGP card applet pub fn list_cards() -> Result> { let cards = card::get_cards().map_err(|err| anyhow!(err))?; @@ -229,7 +233,7 @@ impl OpenPGPCard { Ok(ocs) } - /// Find an OpenPGP card by serial number and return it. + /// Find an OpenPGP card by serial number, open and return it. pub fn open_by_serial(serial: &str) -> Result { let cards = card::get_cards().map_err(|e| { OpenpgpCardError::Smartcard(SmartcardError::Error(format!( @@ -547,10 +551,10 @@ impl OpenPGPCard { Ok(()) } - pub fn verify_pw1_81( + pub fn verify_pw1_for_signing( self, pin: &str, - ) -> Result { + ) -> Result { assert!(pin.len() >= 6); // FIXME: Err let verify = commands::verify_pw1_81(pin.as_bytes().to_vec()); @@ -559,17 +563,14 @@ impl OpenPGPCard { if let Ok(resp) = res { if resp.is_ok() { - return Ok(OpenPGPCardUser { oc: self }); + return Ok(CardSign { oc: self }); } } Err(self) } - pub fn verify_pw1_82( - self, - pin: &str, - ) -> Result { + pub fn verify_pw1(self, pin: &str) -> Result { assert!(pin.len() >= 6); // FIXME: Err let verify = commands::verify_pw1_82(pin.as_bytes().to_vec()); @@ -578,17 +579,14 @@ impl OpenPGPCard { if let Ok(resp) = res { if resp.is_ok() { - return Ok(OpenPGPCardUser { oc: self }); + return Ok(CardUser { oc: self }); } } Err(self) } - pub fn verify_pw3( - self, - pin: &str, - ) -> Result { + pub fn verify_pw3(self, pin: &str) -> Result { assert!(pin.len() >= 8); // FIXME: Err let verify = commands::verify_pw3(pin.as_bytes().to_vec()); @@ -597,7 +595,7 @@ impl OpenPGPCard { if let Ok(resp) = res { if resp.is_ok() { - return Ok(OpenPGPCardAdmin { oc: self }); + return Ok(CardAdmin { oc: self }); } } @@ -605,22 +603,22 @@ impl OpenPGPCard { } } -/// An OpenPGP card after successful verification of PW1 (needs to be split -/// further to model authentication for signing) -pub struct OpenPGPCardUser { - oc: OpenPGPCard, +/// An OpenPGP card after successful verification of PW1 in mode 82 +/// (verification for operations other than signing) +pub struct CardUser { + oc: CardBase, } /// Allow access to fn of OpenPGPCard, through OpenPGPCardUser. -impl Deref for OpenPGPCardUser { - type Target = OpenPGPCard; +impl Deref for CardUser { + type Target = CardBase; fn deref(&self) -> &Self::Target { &self.oc } } -impl OpenPGPCardUser { +impl CardUser { /// Decrypt the ciphertext in `dm`, on the card. pub fn decrypt(&self, dm: DecryptMe) -> Result, OpenpgpCardError> { match dm { @@ -660,7 +658,26 @@ impl OpenPGPCardUser { Ok(resp.data().map(|d| d.to_vec())?) } +} +/// An OpenPGP card after successful verification of PW1 in mode 81 +/// (verification for signing) +pub struct CardSign { + oc: CardBase, +} + +/// Allow access to fn of OpenPGPCard, through OpenPGPCardUser. +impl Deref for CardSign { + type Target = CardBase; + + fn deref(&self) -> &Self::Target { + &self.oc + } +} + +// FIXME: depending on the setting in "PW1 Status byte", only one +// signature can be made after verification for signing +impl CardSign { /// Sign the message in `hash`, on the card. pub fn signature_for_hash( &self, @@ -676,8 +693,7 @@ impl OpenPGPCardUser { TlvEntry::C(vec![ Tlv( Tag(vec![0x06]), - // unwrapping is - // ok, for SHA* + // unwrapping is ok, for SHA* TlvEntry::S(hash.oid().unwrap().to_vec()), ), Tlv(Tag(vec![0x05]), TlvEntry::S(vec![])), @@ -711,21 +727,21 @@ impl OpenPGPCardUser { } } -/// An OpenPGP card after successful verification of PW3 -pub struct OpenPGPCardAdmin { - oc: OpenPGPCard, +/// An OpenPGP card after successful verification of PW3 ("Admin privileges") +pub struct CardAdmin { + oc: CardBase, } /// Allow access to fn of OpenPGPCard, through OpenPGPCardAdmin. -impl Deref for OpenPGPCardAdmin { - type Target = OpenPGPCard; +impl Deref for CardAdmin { + type Target = CardBase; fn deref(&self) -> &Self::Target { &self.oc } } -impl OpenPGPCardAdmin { +impl CardAdmin { pub(crate) fn card(&self) -> &Card { &self.card }