diff options
Diffstat (limited to 'openpgp')
26 files changed, 726 insertions, 342 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 3f470f0f..b52c143c 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -21,8 +21,12 @@ use crate::openpgp::parse::{ MessageLayer, }, }; +use crate::openpgp::policy::Policy; +use crate::openpgp::policy::StandardPolicy as P; pub fn main() { + let p = &P::new(); + let args: Vec<String> = env::args().collect(); if args.len() < 2 { panic!("A simple decryption filter.\n\n\ @@ -38,7 +42,7 @@ pub fn main() { // Now, create a decryptor with a helper using the given Certs. let mut decryptor = - Decryptor::from_reader(io::stdin(), Helper::new(certs), None).unwrap(); + Decryptor::from_reader(p, io::stdin(), Helper::new(p, certs), None).unwrap(); // Finally, stream the decrypted data to stdout. io::copy(&mut decryptor, &mut io::stdout()) @@ -54,11 +58,11 @@ struct Helper { impl Helper { /// Creates a Helper for the given Certs with appropriate secrets. - fn new(certs: Vec<openpgp::Cert>) -> Self { + fn new(p: &dyn Policy, certs: Vec<openpgp::Cert>) -> Self { // Map (sub)KeyIDs to secrets. let mut keys = HashMap::new(); for cert in certs { - for ka in cert.keys().policy(None) + for ka in cert.keys().set_policy(p, None) .for_storage_encryption().for_transport_encryption() { // This only works for unencrypted secret keys. diff --git a/openpgp/examples/encrypt-for.rs b/openpgp/examples/encrypt-for.rs index 63e0e071..b64165b7 100644 --- a/openpgp/examples/encrypt-for.rs +++ b/openpgp/examples/encrypt-for.rs @@ -11,8 +11,11 @@ use crate::openpgp::parse::Parse; use crate::openpgp::serialize::stream::{ Message, LiteralWriter, Encryptor, }; +use crate::openpgp::policy::StandardPolicy as P; fn main() { + let p = &P::new(); + let args: Vec<String> = env::args().collect(); if args.len() < 3 { panic!("A simple encryption filter.\n\n\ @@ -39,7 +42,7 @@ fn main() { certs.iter() .flat_map(|cert| { cert.keys() - .policy(None).alive().revoked(false).key_flags(&mode) + .set_policy(p, None).alive().revoked(false).key_flags(&mode) }) .map(|ka| ka.key().into()) .collect::<Vec<_>>(); diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index 0e109ccd..8258aaf4 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -7,20 +7,24 @@ use crate::openpgp::crypto::SessionKey; use crate::openpgp::types::SymmetricAlgorithm; use crate::openpgp::serialize::stream::*; use crate::openpgp::parse::stream::*; +use crate::openpgp::policy::Policy; +use crate::openpgp::policy::StandardPolicy as P; const MESSAGE: &'static str = "дружба"; fn main() { + let p = &P::new(); + // Generate a key. let key = generate().unwrap(); // Encrypt the message. let mut ciphertext = Vec::new(); - encrypt(&mut ciphertext, MESSAGE, &key).unwrap(); + encrypt(p, &mut ciphertext, MESSAGE, &key).unwrap(); // Decrypt the message. let mut plaintext = Vec::new(); - decrypt(&mut plaintext, &ciphertext, &key).unwrap(); + decrypt(p, &mut plaintext, &ciphertext, &key).unwrap(); assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); } @@ -38,11 +42,13 @@ fn generate() -> openpgp::Result<openpgp::Cert> { } /// Encrypts the given message. -fn encrypt(sink: &mut dyn Write, plaintext: &str, recipient: &openpgp::Cert) - -> openpgp::Result<()> { +fn encrypt(p: &dyn Policy, sink: &mut dyn Write, plaintext: &str, + recipient: &openpgp::Cert) + -> openpgp::Result<()> +{ // Build a vector of recipients to hand to Encryptor. - let mut recipients = recipient - .keys().policy(None).alive().revoked(false) + let mut recipients = + recipient.keys().set_policy(p, None).alive().revoked(false) .for_transport_encryption() .map(|ka| ka.key().into()) .collect::<Vec<_>>(); @@ -72,16 +78,18 @@ fn encrypt(sink: &mut dyn Write, plaintext: &str, recipient: &openpgp::Cert) } /// Decrypts the given message. -fn decrypt(sink: &mut dyn Write, ciphertext: &[u8], recipient: &openpgp::Cert) +fn decrypt(p: &dyn Policy, + sink: &mut dyn Write, ciphertext: &[u8], recipient: &openpgp::Cert) -> openpgp::Result<()> { // Make a helper that that feeds the recipient's secret key to the // decryptor. let helper = Helper { secret: recipient, + policy: p, }; // Now, create a decryptor with a helper using the given Certs. - let mut decryptor = Decryptor::from_bytes(ciphertext, helper, None)?; + let mut decryptor = Decryptor::from_bytes(p, ciphertext, helper, None)?; // Decrypt the data. io::copy(&mut decryptor, sink)?; @@ -91,6 +99,7 @@ fn decrypt(sink: &mut dyn Write, ciphertext: &[u8], recipient: &openpgp::Cert) struct Helper<'a> { secret: &'a openpgp::Cert, + policy: &'a Policy, } impl<'a> VerificationHelper for Helper<'a> { @@ -115,7 +124,7 @@ impl<'a> DecryptionHelper for Helper<'a> { -> openpgp::Result<Option<openpgp::Fingerprint>> where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()> { - let key = self.secret.keys().policy(None) + let key = self.secret.keys().set_policy(self.policy, None) .for_transport_encryption().nth(0).unwrap().key().clone(); // The secret key is not encrypted. diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs index 8df9f1cf..e3142667 100644 --- a/openpgp/examples/generate-sign-verify.rs +++ b/openpgp/examples/generate-sign-verify.rs @@ -6,20 +6,24 @@ extern crate failure; extern crate sequoia_openpgp as openpgp; use crate::openpgp::serialize::stream::*; use crate::openpgp::parse::stream::*; +use crate::openpgp::policy::Policy; +use crate::openpgp::policy::StandardPolicy as P; const MESSAGE: &'static str = "дружба"; fn main() { + let p = &P::new(); + // Generate a key. let key = generate().unwrap(); // Sign the message. let mut signed_message = Vec::new(); - sign(&mut signed_message, MESSAGE, &key).unwrap(); + sign(p, &mut signed_message, MESSAGE, &key).unwrap(); // Verify the message. let mut plaintext = Vec::new(); - verify(&mut plaintext, &signed_message, &key).unwrap(); + verify(p, &mut plaintext, &signed_message, &key).unwrap(); assert_eq!(MESSAGE.as_bytes(), &plaintext[..]); } @@ -37,11 +41,11 @@ fn generate() -> openpgp::Result<openpgp::Cert> { } /// Signs the given message. -fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::Cert) +fn sign(p: &dyn Policy, sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::Cert) -> openpgp::Result<()> { // Get the keypair to do the signing from the Cert. let keypair = tsk - .keys().policy(None).alive().revoked(false).for_signing() + .keys().set_policy(p, None).alive().revoked(false).for_signing() .nth(0).unwrap() .key().clone().mark_parts_secret().unwrap().into_keypair()?; @@ -65,7 +69,8 @@ fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::Cert) } /// Verifies the given message. -fn verify(sink: &mut dyn Write, signed_message: &[u8], sender: &openpgp::Cert) +fn verify(p: &dyn Policy, sink: &mut dyn Write, + signed_message: &[u8], sender: &openpgp::Cert) -> openpgp::Result<()> { // Make a helper that that feeds the sender's public key to the // verifier. @@ -74,7 +79,7 @@ fn verify(sink: &mut dyn Write, signed_message: &[u8], sender: &openpgp::Cert) }; // Now, create a verifier with a helper using the given Certs. - let mut verifier = Verifier::from_bytes(signed_message, helper, None)?; + let mut verifier = Verifier::from_bytes(p, signed_message, helper, None)?; // Verify the data. io::copy(&mut verifier, sink)?; diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs index 5d14ff9e..62042e60 100644 --- a/openpgp/examples/notarize.rs +++ b/openpgp/examples/notarize.rs @@ -12,8 +12,10 @@ use crate::openpgp::{ serialize::Serialize, }; use crate::openpgp::serialize::stream::{Message, LiteralWriter, Signer}; +use crate::openpgp::policy::StandardPolicy as P; fn main() { + let p = &P::new(); let args: Vec<String> = env::args().collect(); if args.len() < 2 { panic!("A simple notarizing filter.\n\n\ @@ -29,7 +31,7 @@ fn main() { let mut n = 0; for key in tsk.keys() - .policy(None).alive().revoked(false).for_signing().secret() + .set_policy(p, None).alive().revoked(false).for_signing().secret() .map(|ka| ka.key()) { keys.push({ diff --git a/openpgp/examples/pad.rs b/openpgp/examples/pad.rs index f0792d4e..68efa655 100644 --- a/openpgp/examples/pad.rs +++ b/openpgp/examples/pad.rs @@ -13,8 +13,10 @@ use crate::openpgp::serialize::stream::{ Message, LiteralWriter, Encryptor, Recipient, }; use crate::openpgp::serialize::padding::*; +use crate::openpgp::policy::StandardPolicy as P; fn main() { + let p = &P::new(); let args: Vec<String> = env::args().collect(); if args.len() < 3 { panic!("A simple encryption filter.\n\n\ @@ -41,7 +43,7 @@ fn main() { .iter() .flat_map(|cert| { cert.keys() - .policy(None).alive().revoked(false).key_flags(&mode) + .set_policy(p, None).alive().revoked(false).key_flags(&mode) }) .map(|ka| Recipient::new(KeyID::wildcard(), ka.key())) .collect::<Vec<_>>(); diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs index 4d228f34..e93cd0e2 100644 --- a/openpgp/examples/sign-detached.rs +++ b/openpgp/examples/sign-detached.rs @@ -8,8 +8,10 @@ extern crate sequoia_openpgp as openpgp; use crate::openpgp::armor; use crate::openpgp::parse::Parse; use crate::openpgp::serialize::stream::{Message, Signer}; +use crate::openpgp::policy::StandardPolicy as P; fn main() { + let p = &P::new(); let args: Vec<String> = env::args().collect(); if args.len() < 2 { panic!("A simple filter creating a detached signature.\n\n\ @@ -25,7 +27,7 @@ fn main() { let mut n = 0; for key in tsk - .keys().policy(None).alive().revoked(false).for_signing().secret() + .keys().set_policy(p, None).alive().revoked(false).for_signing().secret() .map(|ka| ka.key()) { keys.push({ diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs index b6bedeb4..85565b2e 100644 --- a/openpgp/examples/sign.rs +++ b/openpgp/examples/sign.rs @@ -7,8 +7,10 @@ extern crate sequoia_openpgp as openpgp; use crate::openpgp::armor; use crate::openpgp::parse::Parse; use crate::openpgp::serialize::stream::{Message, LiteralWriter, Signer}; +use crate::openpgp::policy::StandardPolicy as P; fn main() { + let p = &P::new(); let args: Vec<String> = env::args().collect(); if args.len() < 2 { panic!("A simple signing filter.\n\n\ @@ -24,7 +26,7 @@ fn main() { let mut n = 0; for key in tsk.keys() - .policy(None).alive().revoked(false).for_signing().secret() + .set_policy(p, None).alive().revoked(false).for_signing().secret() .map(|ka| ka.key()) { keys.push({ diff --git a/openpgp/src/autocrypt.rs b/openpgp/src/autocrypt.rs index b308e29d..cb579211 100644 --- a/openpgp/src/autocrypt.rs +++ b/openpgp/src/autocrypt.rs @@ -36,6 +36,7 @@ use crate::serialize::stream::{ Message, LiteralWriter, Encryptor, }; use crate::crypto::Password; +use crate::policy::Policy; /// Version of Autocrypt to use. `Autocrypt::default()` always returns the /// latest version. @@ -97,7 +98,8 @@ impl AutocryptHeader { } /// Creates a new "Autocrypt" header. - pub fn new_sender<'a, P>(cert: &Cert, addr: &str, prefer_encrypt: P) + pub fn new_sender<'a, P>(policy: &dyn Policy, + cert: &Cert, addr: &str, prefer_encrypt: P) -> Result<Self> where P: Into<Option<&'a str>> { @@ -128,7 +130,7 @@ impl AutocryptHeader { } // The UserIDs matching ADDR. - for uidb in cert.userids().policy(None) { + for uidb in cert.userids().set_policy(policy, None) { // XXX: Fix match once we have the rfc2822-name-addr. if let Ok(Some(a)) = uidb.userid().email() { if &a == addr { @@ -773,6 +775,7 @@ mod test { use super::*; use crate::Fingerprint; + use crate::policy::StandardPolicy as P; #[test] fn decode_test() { @@ -1067,8 +1070,10 @@ In the light of the Efail vulnerability I am asking myself if it's #[test] fn autocrypt_header_new() { + let p = &P::new(); + let cert = Cert::from_bytes(crate::tests::key("testy.pgp")).unwrap(); - let header = AutocryptHeader::new_sender(&cert, "testy@example.org", + let header = AutocryptHeader::new_sender(p, &cert, "testy@example.org", "mutual").unwrap(); let mut buf = Vec::new(); write!(&mut buf, "Autocrypt: ").unwrap(); diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index 205099c1..cd9b2079 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -8,6 +8,7 @@ use crate::{ packet::Signature, Result, RevocationStatus, + policy::Policy, }; /// A certificate's component and its associated data. @@ -49,12 +50,13 @@ impl<'a, C> ComponentAmalgamation<'a, C> { /// time, if any. /// /// Note: this function is not exported. Users of this interface - /// should do: ca.policy(time)?.binding_signature(). - fn binding_signature<T>(&self, time: T) -> Option<&'a Signature> + /// should do: ca.set_policy(policy, time)?.binding_signature(). + fn binding_signature<T>(&self, policy: &dyn Policy, time: T) + -> Option<&'a Signature> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - self.binding.binding_signature(time) + self.binding.binding_signature(policy, time) } /// Sets the reference time for the amalgamation. @@ -63,14 +65,15 @@ impl<'a, C> ComponentAmalgamation<'a, C> { /// /// This transforms the `ComponentAmalgamation` into a /// `ValidComponentAmalgamation`. - pub fn policy<T>(self, time: T) + pub fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<ValidComponentAmalgamation<'a, C>> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - if let Some(binding_signature) = self.binding_signature(time) { + if let Some(binding_signature) = self.binding_signature(policy, time) { Ok(ValidComponentAmalgamation { a: self, + policy: policy, time: time, binding_signature: binding_signature, }) @@ -98,6 +101,7 @@ impl<'a> ComponentAmalgamation<'a, crate::packet::UserAttribute> { #[derive(Debug, Clone)] pub struct ValidComponentAmalgamation<'a, C> { a: ComponentAmalgamation<'a, C>, + policy: &'a dyn Policy, // The reference time. time: SystemTime, // The binding signature at time `time`. (This is just a cache.) @@ -131,25 +135,25 @@ impl<'a, C> ValidComponentAmalgamation<'a, C> /// deterministic, but undefined manner. pub(super) fn primary(cert: &'a Cert, iter: std::slice::Iter<'a, ComponentBinding<C>>, - t: SystemTime) - -> Option<ValidComponentAmalgamation<'a, C>> + policy: &'a dyn Policy, t: SystemTime) + -> Option<ValidComponentAmalgamation<'a, C>> { use std::cmp::Ordering; // Filter out components that are not alive at time `t`. - // - // While we have the binding signature, extract a few - // properties to avoid recomputing the same thing multiple - // times. + // + // While we have the binding signature, extract a few + // properties to avoid recomputing the same thing multiple + // times. iter.filter_map(|c| { // No binding signature at time `t` => not alive. - let sig = c.binding_signature(t)?; + let sig = c.binding_signature(policy, t)?; if !sig.signature_alive(t, std::time::Duration::new(0, 0)).is_ok() { return None; } - let revoked = c._revoked(false, Some(sig), t); + let revoked = c._revoked(policy, t, false, Some(sig)); let primary = sig.primary_userid().unwrap_or(false); let signature_creation_time = sig.signature_creation_time()?; @@ -185,7 +189,7 @@ impl<'a, C> ValidComponentAmalgamation<'a, C> } }) .and_then(|c| ComponentAmalgamation::new(cert, (c.0).0) - .policy(t).ok()) + .set_policy(policy, t).ok()) } } @@ -203,10 +207,13 @@ pub trait Amalgamation<'a> { /// time is greater than or equal to `t_c` and less than `t_e`. fn time(&self) -> SystemTime; + /// Returns the amalgamation's policy. + fn policy(&self) -> &'a dyn Policy; + /// Changes the amalgamation's policy. /// /// If `time` is `None`, the current time is used. - fn policy<T>(self, time: T) -> Result<Self> + fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self> where Self: Sized, T: Into<Option<time::SystemTime>>; /// Returns the component's binding signature as of the reference time. @@ -228,13 +235,13 @@ pub trait Amalgamation<'a> { /// Returns the certificate's revocation status as of the /// amalgamtion's reference time. fn cert_revoked(&self) -> RevocationStatus<'a> { - self.cert().revoked(self.time()) + self.cert().revoked(self.policy(), self.time()) } /// Returns whether the certificateis alive as of the /// amalgamtion's reference time. fn cert_alive(&self) -> Result<()> { - self.cert().alive(self.time()) + self.cert().alive(self.policy(), self.time()) } } @@ -256,14 +263,20 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { self.time } + /// Returns the amalgamation's policy. + fn policy(&self) -> &'a dyn Policy + { + self.policy + } + /// Changes the amalgamation's policy. /// /// If `time` is `None`, the current time is used. - fn policy<T>(self, time: T) -> Result<Self> + fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - self.a.policy(time) + self.a.set_policy(policy, time) } /// Returns the component's binding signature as of the reference time. @@ -277,7 +290,7 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { /// Subpackets on direct key signatures apply to all components of /// the certificate. fn direct_key_signature(&self) -> Option<&'a Signature> { - self.cert.primary.binding_signature(self.time()) + self.cert.primary.binding_signature(self.policy(), self.time()) } /// Returns the component's revocation status as of the amalgamation's @@ -285,7 +298,8 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { /// < |