Experiment: wrap Arc<Mutex<CardSign>> in CardSigner

This commit is contained in:
Heiko Schaefer 2021-07-12 13:54:59 +02:00
parent 3872b585d8
commit 89745c0268
4 changed files with 40 additions and 34 deletions

View file

@ -24,6 +24,7 @@ use openpgp_card::{
errors::OpenpgpCardError, CardAdmin, CardSign, CardUploadableKey, errors::OpenpgpCardError, CardAdmin, CardSign, CardUploadableKey,
CardUser, EccKey, EccType, KeyType, PrivateKeyMaterial, RSAKey, CardUser, EccKey, EccType, KeyType, PrivateKeyMaterial, RSAKey,
}; };
use std::sync::{Arc, Mutex};
mod decryptor; mod decryptor;
mod signer; mod signer;
@ -282,7 +283,7 @@ pub fn decrypt(
} }
pub fn sign( pub fn sign(
ocu: &mut CardSign, ocu: Arc<Mutex<CardSign>>,
cert: &sequoia_openpgp::Cert, cert: &sequoia_openpgp::Cert,
input: &mut dyn io::Read, input: &mut dyn io::Read,
) -> Result<String> { ) -> Result<String> {

View file

@ -10,6 +10,7 @@ use sequoia_openpgp::Cert;
use openpgp_card::{CardBase, KeyType}; use openpgp_card::{CardBase, KeyType};
use openpgp_card_scdc::ScdClient; use openpgp_card_scdc::ScdClient;
use std::sync::{Arc, Mutex};
// Filename of test key and test message to use: // Filename of test key and test message to use:
@ -197,7 +198,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let text = "Hello world, I am signed."; let text = "Hello world, I am signed.";
let res = openpgp_card_sequoia::sign( let res = openpgp_card_sequoia::sign(
&mut oc_user, Arc::new(Mutex::new(oc_user)),
&cert, &cert,
&mut text.as_bytes(), &mut text.as_bytes(),
); );

View file

@ -15,27 +15,28 @@ use openpgp_card::CardSign;
use openpgp_card::Hash; use openpgp_card::Hash;
use crate::PublicKey; use crate::PublicKey;
use std::sync::{Arc, Mutex};
pub(crate) struct CardSigner<'a> { pub(crate) struct CardSigner {
/// The OpenPGP card (authenticated to allow signing operations) /// The OpenPGP card (authenticated to allow signing operations)
ocu: &'a mut CardSign, ocu: Arc<Mutex<CardSign>>,
/// The matching public key for the card's signing key /// The matching public key for the card's signing key
public: PublicKey, public: PublicKey,
} }
impl<'a> CardSigner<'a> { impl CardSigner {
/// Try to create a CardSigner. /// Try to create a CardSigner.
/// ///
/// 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(
ocs: &'a mut CardSign, cs: Arc<Mutex<CardSign>>,
cert: &openpgp::Cert, cert: &openpgp::Cert,
policy: &dyn Policy, policy: &dyn Policy,
) -> Result<CardSigner<'a>, OpenpgpCardError> { ) -> Result<CardSigner, OpenpgpCardError> {
// Get the fingerprint for the signing key from the card. // Get the fingerprint for the signing key from the card.
let fps = ocs.get_fingerprints()?; let fps = cs.lock().unwrap().get_fingerprints()?;
let fp = fps.signature(); let fp = fps.signature();
if let Some(fp) = fp { if let Some(fp) = fp {
@ -58,7 +59,7 @@ impl<'a> CardSigner<'a> {
let public = keys[0].clone(); let public = keys[0].clone();
Ok(CardSigner { Ok(CardSigner {
ocu: ocs, ocu: cs,
public: public.role_as_unspecified().clone(), public: public.role_as_unspecified().clone(),
}) })
} else { } else {
@ -75,7 +76,7 @@ impl<'a> CardSigner<'a> {
} }
} }
impl<'a> crypto::Signer for CardSigner<'a> { impl<'a> crypto::Signer for CardSigner {
fn public(&self) -> &PublicKey { fn public(&self) -> &PublicKey {
&self.public &self.public
} }
@ -98,28 +99,22 @@ impl<'a> crypto::Signer for CardSigner<'a> {
PublicKeyAlgorithm::RSAEncryptSign, PublicKeyAlgorithm::RSAEncryptSign,
mpi::PublicKey::RSA { .. }, mpi::PublicKey::RSA { .. },
) => { ) => {
let sig = match hash_algo { let hash = match hash_algo {
openpgp::types::HashAlgorithm::SHA256 => { openpgp::types::HashAlgorithm::SHA256 => Hash::SHA256(
let hash = digest
Hash::SHA256(digest.try_into().map_err(|_| { .try_into()
anyhow!("invalid slice length") .map_err(|_| anyhow!("invalid slice length"))?,
})?); ),
self.ocu.signature_for_hash(hash)? openpgp::types::HashAlgorithm::SHA384 => Hash::SHA384(
} digest
openpgp::types::HashAlgorithm::SHA384 => { .try_into()
let hash = .map_err(|_| anyhow!("invalid slice length"))?,
Hash::SHA384(digest.try_into().map_err(|_| { ),
anyhow!("invalid slice length") openpgp::types::HashAlgorithm::SHA512 => Hash::SHA512(
})?); digest
self.ocu.signature_for_hash(hash)? .try_into()
} .map_err(|_| anyhow!("invalid slice length"))?,
openpgp::types::HashAlgorithm::SHA512 => { ),
let hash =
Hash::SHA512(digest.try_into().map_err(|_| {
anyhow!("invalid slice length")
})?);
self.ocu.signature_for_hash(hash)?
}
_ => { _ => {
return Err(anyhow!( return Err(anyhow!(
"Unsupported hash algorithm for RSA {:?}", "Unsupported hash algorithm for RSA {:?}",
@ -128,12 +123,21 @@ impl<'a> crypto::Signer for CardSigner<'a> {
} }
}; };
let cs = self.ocu.clone();
let mut cs = cs.lock().unwrap();
let sig = cs.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 })
} }
(PublicKeyAlgorithm::EdDSA, mpi::PublicKey::EdDSA { .. }) => { (PublicKeyAlgorithm::EdDSA, mpi::PublicKey::EdDSA { .. }) => {
let hash = Hash::EdDSA(digest); let hash = Hash::EdDSA(digest);
let sig = self.ocu.signature_for_hash(hash)?;
let cs = self.ocu.clone();
let mut cs = cs.lock().unwrap();
let sig = cs.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..]);

View file

@ -30,7 +30,7 @@ pub trait CardClient {
fn transmit(&mut self, cmd: &[u8], buf_size: usize) -> Result<Vec<u8>>; fn transmit(&mut self, cmd: &[u8], buf_size: usize) -> Result<Vec<u8>>;
} }
pub type CardClientBox = Box<dyn CardClient + Send + Sync>; pub type CardClientBox = Box<dyn CardClient + Send>;
/// Information about the capabilities of the card. /// Information about the capabilities of the card.
/// (feature configuration from card metadata) /// (feature configuration from card metadata)