Implement signing for auth slot
This commit is contained in:
parent
141fe3d136
commit
43a9abdabd
3 changed files with 47 additions and 8 deletions
|
@ -357,6 +357,14 @@ impl<'app, 'open> User<'app, 'open> {
|
||||||
) -> Result<CardDecryptor<'_, 'app>, Error> {
|
) -> Result<CardDecryptor<'_, 'app>, Error> {
|
||||||
CardDecryptor::new(&mut self.oc.opt, cert, touch_prompt)
|
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
|
/// 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
|
// 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(&mut self.oc.opt, cert, touch_prompt)
|
CardSigner::with_cert(&mut self.oc.opt, cert, touch_prompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn signer_from_pubkey(
|
pub fn signer_from_pubkey(
|
||||||
|
|
|
@ -25,6 +25,9 @@ pub struct CardSigner<'a, 'app> {
|
||||||
|
|
||||||
/// Callback function to signal if touch confirmation is needed
|
/// Callback function to signal if touch confirmation is needed
|
||||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||||
|
|
||||||
|
/// sign or auth? (true = auth)
|
||||||
|
auth: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'app> CardSigner<'a, 'app> {
|
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
|
/// 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(crate) fn new(
|
pub(crate) fn with_cert(
|
||||||
ca: &'a mut OpenPgpTransaction<'app>,
|
ca: &'a mut OpenPgpTransaction<'app>,
|
||||||
cert: &openpgp::Cert,
|
cert: &openpgp::Cert,
|
||||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||||
|
@ -71,6 +74,20 @@ impl<'a, 'app> CardSigner<'a, 'app> {
|
||||||
ca,
|
ca,
|
||||||
public,
|
public,
|
||||||
touch_prompt,
|
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?
|
// FIXME: use cached ARD value from caller?
|
||||||
let ard = self.ca.application_related_data()?;
|
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:
|
// Touch is required if:
|
||||||
// - the card supports the feature
|
// - the card supports the feature
|
||||||
// - and the policy is set to a value other than 'Off'
|
// - 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()
|
uif.touch_policy().touch_required()
|
||||||
} else {
|
} else {
|
||||||
false
|
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
|
// This fn prepares the data structures that openpgp-card needs to
|
||||||
// perform the signing operation.
|
// perform the signing operation.
|
||||||
//
|
//
|
||||||
// (7.2.10 PSO: COMPUTE DIGITAL SIGNATURE)
|
// (7.2.10 PSO: COMPUTE DIGITAL SIGNATURE)
|
||||||
|
// or (7.2.13 INTERNAL AUTHENTICATE)
|
||||||
|
|
||||||
match (self.public.pk_algo(), self.public.mpis()) {
|
match (self.public.pk_algo(), self.public.mpis()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -136,7 +167,7 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
|
||||||
(self.touch_prompt)();
|
(self.touch_prompt)();
|
||||||
}
|
}
|
||||||
|
|
||||||
let sig = self.ca.signature_for_hash(hash)?;
|
let sig = sig_fn(self.ca, 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 })
|
||||||
|
@ -148,7 +179,7 @@ impl<'a, 'app> crypto::Signer for CardSigner<'a, 'app> {
|
||||||
(self.touch_prompt)();
|
(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 r = mpi::MPI::new(&sig[..32]);
|
||||||
let s = 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)();
|
(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 len_2 = sig.len() / 2;
|
||||||
let r = mpi::MPI::new(&sig[..len_2]);
|
let r = mpi::MPI::new(&sig[..len_2]);
|
||||||
|
|
|
@ -434,7 +434,7 @@ pub fn sign(
|
||||||
) -> 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_tx, cert, touch_prompt)?;
|
let s = signer::CardSigner::with_cert(card_tx, cert, touch_prompt)?;
|
||||||
|
|
||||||
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()?;
|
||||||
|
|
Loading…
Reference in a new issue