Rename structs that represent different verification states of the OpenPGP card.

This commit is contained in:
Heiko Schaefer 2021-07-02 14:21:50 +02:00
parent 3fcb78caa5
commit 920da0442b
7 changed files with 76 additions and 60 deletions

View file

@ -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<CardDecryptor<'a>, OpenpgpCardError> {

View file

@ -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<String>,
@ -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<SecretParts>,
key_type: KeyType,
password: Option<String>,
@ -260,7 +260,7 @@ pub fn upload_key(
}
pub fn decrypt(
ocu: &OpenPGPCardUser,
ocu: &CardUser,
cert: &sequoia_openpgp::Cert,
msg: Vec<u8>,
) -> Result<Vec<u8>> {
@ -282,7 +282,7 @@ pub fn decrypt(
}
pub fn sign(
ocu: &OpenPGPCardUser,
ocu: &CardSign,
cert: &sequoia_openpgp::Cert,
input: &mut dyn io::Read,
) -> Result<String> {

View file

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

View file

@ -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<CardSigner<'a>, 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 {

View file

@ -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<Response, OpenpgpCardError> {
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<Vec<u8>, OpenpgpCardError> {
log::trace!(" -> full APDU command: {:x?}", cmd);
log::trace!(" serialized: {:x?}", cmd.serialize(ext));

View file

@ -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<dyn CardUploadableKey>,
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<u8>,

View file

@ -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<Vec<Self>> {
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<Self, OpenpgpCardError> {
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<OpenPGPCardUser, OpenPGPCard> {
) -> Result<CardSign, CardBase> {
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<OpenPGPCardUser, OpenPGPCard> {
pub fn verify_pw1(self, pin: &str) -> Result<CardUser, CardBase> {
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<OpenPGPCardAdmin, OpenPGPCard> {
pub fn verify_pw3(self, pin: &str) -> Result<CardAdmin, CardBase> {
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<Vec<u8>, 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
}