Implement signing for auth slot

This commit is contained in:
Heiko Schaefer 2022-06-20 19:59:12 +02:00
parent 141fe3d136
commit 43a9abdabd
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
3 changed files with 47 additions and 8 deletions

View file

@ -357,6 +357,14 @@ impl<'app, 'open> User<'app, 'open> {
) -> Result<CardDecryptor<'_, 'app>, Error> {
CardDecryptor::new(&mut self.oc.opt, cert, touch_prompt)
}
pub fn authenticator(
&mut self,
pubkey: PublicKey,
touch_prompt: &'open (dyn Fn() + Send + Sync),
) -> CardSigner<'_, 'app> {
CardSigner::with_pubkey_for_auth(&mut self.oc.opt, pubkey, touch_prompt)
}
}
/// An OpenPGP card after successfully verifying PW1 in mode 81
@ -374,7 +382,7 @@ impl<'app, 'open> Sign<'app, 'open> {
// FIXME: depending on the setting in "PW1 Status byte", only one
// signature can be made after verification for signing
CardSigner::new(&mut self.oc.opt, cert, touch_prompt)
CardSigner::with_cert(&mut self.oc.opt, cert, touch_prompt)
}
pub fn signer_from_pubkey(

View file

@ -25,6 +25,9 @@ pub struct CardSigner<'a, 'app> {
/// Callback function to signal if touch confirmation is needed
touch_prompt: &'a (dyn Fn() + Send + Sync),
/// sign or auth? (true = auth)
auth: bool,
}
impl<'a, 'app> CardSigner<'a, 'app> {
@ -32,7 +35,7 @@ impl<'a, 'app> CardSigner<'a, 'app> {
///
/// An Error is returned if no match between the card's signing
/// key and a (sub)key of `cert` can be made.
pub(crate) fn new(
pub(crate) fn with_cert(
ca: &'a mut OpenPgpTransaction<'app>,
cert: &openpgp::Cert,
touch_prompt: &'a (dyn Fn() + Send + Sync),
@ -71,6 +74,20 @@ impl<'a, 'app> CardSigner<'a, 'app> {
ca,
public,
touch_prompt,
auth: false,
}
}
pub(crate) fn with_pubkey_for_auth(
ca: &'a mut OpenPgpTransaction<'app>,
public: PublicKey,
touch_prompt: &'a (dyn Fn() + Send + Sync),
) -> CardSigner<'a, 'app> {
CardSigner {
ca,
public,
touch_prompt,
auth: true,
}
}
}
@ -88,21 +105,35 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
// FIXME: use cached ARD value from caller?
let ard = self.ca.application_related_data()?;
// Get UIF setting for the sign or auth slot
let uif = if !self.auth {
ard.uif_pso_cds()?
} else {
ard.uif_pso_aut()?
};
// Touch is required if:
// - the card supports the feature
// - and the policy is set to a value other than 'Off'
let touch_required = if let Some(uif) = ard.uif_pso_cds()? {
let touch_required = if let Some(uif) = uif {
uif.touch_policy().touch_required()
} else {
false
};
// Delegate a signing operation to the OpenPGP card.
let sig_fn = if !self.auth {
OpenPgpTransaction::signature_for_hash
} else {
OpenPgpTransaction::authenticate_for_hash
};
// Delegate a signing (or auth) operation to the OpenPGP card.
//
// This fn prepares the data structures that openpgp-card needs to
// perform the signing operation.
//
// (7.2.10 PSO: COMPUTE DIGITAL SIGNATURE)
// or (7.2.13 INTERNAL AUTHENTICATE)
match (self.public.pk_algo(), self.public.mpis()) {
#[allow(deprecated)]
@ -136,7 +167,7 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
(self.touch_prompt)();
}
let sig = self.ca.signature_for_hash(hash)?;
let sig = sig_fn(self.ca, hash)?;
let mpi = mpi::MPI::new(&sig[..]);
Ok(mpi::Signature::RSA { s: mpi })
@ -148,7 +179,7 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
(self.touch_prompt)();
}
let sig = self.ca.signature_for_hash(hash)?;
let sig = sig_fn(self.ca, hash)?;
let r = mpi::MPI::new(&sig[..32]);
let s = mpi::MPI::new(&sig[32..]);
@ -167,7 +198,7 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
(self.touch_prompt)();
}
let sig = self.ca.signature_for_hash(hash)?;
let sig = sig_fn(self.ca, hash)?;
let len_2 = sig.len() / 2;
let r = mpi::MPI::new(&sig[..len_2]);

View file

@ -434,7 +434,7 @@ pub fn sign(
) -> Result<String> {
let mut armorer = armor::Writer::new(vec![], armor::Kind::Signature)?;
{
let s = signer::CardSigner::new(card_tx, cert, touch_prompt)?;
let s = signer::CardSigner::with_cert(card_tx, cert, touch_prompt)?;
let message = Message::new(&mut armorer);
let mut message = Signer::new(message, s).detached().build()?;