Add callback Fn for touch confirmation prompt for decryption operations.
This commit is contained in:
parent
079cc32427
commit
374f9eec89
8 changed files with 49 additions and 9 deletions
|
@ -72,7 +72,7 @@ pub fn test_decrypt(
|
|||
|
||||
let p = StandardPolicy::new();
|
||||
|
||||
let res = openpgp_card_sequoia::util::decrypt(&mut pgpt, &cert, msg.into_bytes(), &p)?;
|
||||
let res = openpgp_card_sequoia::util::decrypt(&mut pgpt, &cert, msg.into_bytes(), &|| {}, &p)?;
|
||||
let plain = String::from_utf8_lossy(&res);
|
||||
|
||||
assert_eq!(plain, "Hello world!\n");
|
||||
|
|
|
@ -35,7 +35,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
let p = StandardPolicy::new();
|
||||
let cert = Cert::from_file(cert_file)?;
|
||||
let d = user.decryptor(&cert)?;
|
||||
let d = user.decryptor(&cert, &|| {
|
||||
println!("Touch confirmation needed for decryption")
|
||||
})?;
|
||||
let stdin = std::io::stdin();
|
||||
|
||||
let mut stdout = std::io::stdout();
|
||||
|
|
|
@ -169,7 +169,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
println!("Encrypted message:\n{}", msg);
|
||||
|
||||
let sp = StandardPolicy::new();
|
||||
let d = user.decryptor(&cert)?;
|
||||
let d = user.decryptor(&cert, &|| {
|
||||
println!("Touch confirmation needed for decryption")
|
||||
})?;
|
||||
let res = sq_util::decryption_helper(d, msg.into_bytes(), &sp)?;
|
||||
|
||||
let plain = String::from_utf8_lossy(&res);
|
||||
|
|
|
@ -340,8 +340,12 @@ pub struct User<'app, 'open> {
|
|||
}
|
||||
|
||||
impl<'app, 'open> User<'app, 'open> {
|
||||
pub fn decryptor(&mut self, cert: &Cert) -> Result<CardDecryptor<'_, 'app>, Error> {
|
||||
CardDecryptor::new(&mut self.oc.opt, cert)
|
||||
pub fn decryptor(
|
||||
&mut self,
|
||||
cert: &Cert,
|
||||
touch_prompt: &'open (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardDecryptor<'_, 'app>, Error> {
|
||||
CardDecryptor::new(&mut self.oc.opt, cert, touch_prompt)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@ pub struct CardDecryptor<'a, 'app> {
|
|||
|
||||
/// The matching public key for the card's decryption key
|
||||
public: PublicKey,
|
||||
|
||||
/// Callback function to signal if touch confirmation is needed
|
||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||
}
|
||||
|
||||
impl<'a, 'app> CardDecryptor<'a, 'app> {
|
||||
|
@ -34,6 +37,7 @@ impl<'a, 'app> CardDecryptor<'a, 'app> {
|
|||
pub fn new(
|
||||
ca: &'a mut OpenPgpTransaction<'app>,
|
||||
cert: &Cert,
|
||||
touch_prompt: &'a (dyn Fn() + Send + Sync),
|
||||
) -> Result<CardDecryptor<'a, 'app>, Error> {
|
||||
// Get the fingerprint for the decryption key from the card.
|
||||
let ard = ca.application_related_data()?;
|
||||
|
@ -46,7 +50,11 @@ impl<'a, 'app> CardDecryptor<'a, 'app> {
|
|||
|
||||
if let Some(eka) = sq_util::get_subkey_by_fingerprint(cert, &fp)? {
|
||||
let public = eka.key().clone();
|
||||
Ok(Self { ca, public })
|
||||
Ok(Self {
|
||||
ca,
|
||||
public,
|
||||
touch_prompt,
|
||||
})
|
||||
} else {
|
||||
Err(Error::InternalError(format!(
|
||||
"Failed to find (sub)key {} in cert",
|
||||
|
@ -71,6 +79,18 @@ impl<'a, 'app> crypto::Decryptor for CardDecryptor<'a, 'app> {
|
|||
ciphertext: &mpi::Ciphertext,
|
||||
_plaintext_len: Option<usize>,
|
||||
) -> openpgp::Result<crypto::SessionKey> {
|
||||
// FIXME: use cached ARD value from caller?
|
||||
let ard = self.ca.application_related_data()?;
|
||||
|
||||
// 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_dec()? {
|
||||
uif.touch_policy().touch_required()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Delegate a decryption operation to the OpenPGP card.
|
||||
//
|
||||
// This fn prepares the data structures that openpgp-card needs to
|
||||
|
@ -80,6 +100,11 @@ impl<'a, 'app> crypto::Decryptor for CardDecryptor<'a, 'app> {
|
|||
match (ciphertext, self.public.mpis()) {
|
||||
(mpi::Ciphertext::RSA { c: ct }, mpi::PublicKey::RSA { .. }) => {
|
||||
let dm = Cryptogram::RSA(ct.value());
|
||||
|
||||
if touch_required {
|
||||
(self.touch_prompt)();
|
||||
}
|
||||
|
||||
let dec = self.ca.decipher(dm)?;
|
||||
|
||||
let sk = openpgp::crypto::SessionKey::from(&dec[..]);
|
||||
|
@ -100,6 +125,10 @@ impl<'a, 'app> crypto::Decryptor for CardDecryptor<'a, 'app> {
|
|||
Cryptogram::ECDH(e.value())
|
||||
};
|
||||
|
||||
if touch_required {
|
||||
(self.touch_prompt)();
|
||||
}
|
||||
|
||||
// Decryption operation on the card
|
||||
let mut dec = self.ca.decipher(dm)?;
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
//! # let (cert, _) =
|
||||
//! # CertBuilder::general_purpose(None, Some("alice@example.org"))
|
||||
//! # .generate()?;
|
||||
//! let decryptor = user.decryptor(&cert);
|
||||
//! let decryptor = user.decryptor(&cert, &|| { println!("Touch confirmation needed for decryption") });
|
||||
//!
|
||||
//! // Perform decryption operation(s)
|
||||
//! // ..
|
||||
|
|
|
@ -404,13 +404,14 @@ pub fn decrypt(
|
|||
card_tx: &'_ mut OpenPgpTransaction<'_>,
|
||||
cert: &Cert,
|
||||
msg: Vec<u8>,
|
||||
touch_prompt: &(dyn Fn() + Send + Sync),
|
||||
p: &dyn Policy,
|
||||
) -> Result<Vec<u8>> {
|
||||
let mut decrypted = Vec::new();
|
||||
{
|
||||
let reader = io::BufReader::new(&msg[..]);
|
||||
|
||||
let d = decryptor::CardDecryptor::new(card_tx, cert)?;
|
||||
let d = decryptor::CardDecryptor::new(card_tx, cert, touch_prompt)?;
|
||||
|
||||
let db = DecryptorBuilder::from_reader(reader)?;
|
||||
let mut decryptor = db.with_policy(p, None, d)?;
|
||||
|
|
|
@ -892,7 +892,9 @@ fn decrypt(
|
|||
let user_pin = util::get_pin(&mut open, pin_file, ENTER_USER_PIN);
|
||||
|
||||
let mut user = util::verify_to_user(&mut open, user_pin.as_deref())?;
|
||||
let d = user.decryptor(&cert)?;
|
||||
let d = user.decryptor(&cert, &|| {
|
||||
println!("Touch confirmation needed for decryption")
|
||||
})?;
|
||||
|
||||
let db = DecryptorBuilder::from_reader(input)?;
|
||||
let mut decryptor = db.with_policy(&p, None, d)?;
|
||||
|
|
Loading…
Reference in a new issue