diff options
author | Neal H. Walfield <neal@pep.foundation> | 2022-10-31 20:38:02 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2022-11-15 19:46:48 +0100 |
commit | 095eed89ee4e6b4f924ff2f43aaadb5fd30c20a7 (patch) | |
tree | 8f04100e20aeb8209bfb2bf939f9d91cd97870a6 /openpgp | |
parent | be2de85d31674b6790b2f02bdac9bf7e7b4810aa (diff) |
openpgp: Simplify using a good list with a StandardPolicy.
- To use a good list, we need to reject all options by default and
then only enable those on the good list.
- Add a mechanism to reject all options in a particular
category (hash algorithms, critical subpackets, asymmetric
algorithms, symmetric algorithms, AEAD algorithms, and packet
tags).
- See #941.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/NEWS | 6 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 166 | ||||
-rw-r--r-- | openpgp/src/policy/cutofflist.rs | 12 |
3 files changed, 183 insertions, 1 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS index 1ff35f6a..626e0e02 100644 --- a/openpgp/NEWS +++ b/openpgp/NEWS @@ -18,6 +18,12 @@ - DataFormat::variants. - packet::Tag::variants. - SubpacketTag::variants. + - StandardPolicy::reject_all_hashes + - StandardPolicy::reject_all_critical_subpackets + - StandardPolicy::reject_all_asymmetric_algos + - StandardPolicy::reject_all_symmetric_algos + - StandardPolicy::reject_all_aead_algos + - StandardPolicy::reject_all_packet_tags * Changes in 1.10.0 ** New functionality - Cert::insert_packets2 diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs index 704a7ea8..bc9281c0 100644 --- a/openpgp/src/policy.rs +++ b/openpgp/src/policy.rs @@ -909,6 +909,18 @@ impl<'a> StandardPolicy<'a> { self.second_pre_image_resistant_hash_algos.set(h, REJECT); } + /// Considers all hash algorithms to be insecure. + /// + /// Causes all hash algorithms to be considered insecure in all + /// security contexts. + /// + /// This is useful when using a good list to determine what + /// algorithms are allowed. + pub fn reject_all_hashes(&mut self) { + self.collision_resistant_hash_algos.reject_all(); + self.second_pre_image_resistant_hash_algos.reject_all(); + } + /// Considers `h` to be insecure in all security contexts starting /// at time `t`. /// @@ -1114,6 +1126,14 @@ impl<'a> StandardPolicy<'a> { self.critical_subpackets.set(s, REJECT); } + /// Considers all critical subpackets to be insecure. + /// + /// This is useful when using a good list to determine what + /// critical subpackets are allowed. + pub fn reject_all_critical_subpackets(&mut self) { + self.critical_subpackets.reject_all(); + } + /// Considers `s` to be insecure starting at `cutoff`. /// /// A cutoff of `None` means that there is no cutoff and the @@ -1153,6 +1173,14 @@ impl<'a> StandardPolicy<'a> { self.asymmetric_algos.set(a, REJECT); } + /// Considers all asymmetric algorithms to be insecure. + /// + /// This is useful when using a good list to determine what + /// algorithms are allowed. + pub fn reject_all_asymmetric_algos(&mut self) { + self.asymmetric_algos.reject_all(); + } + /// Considers `a` to be insecure starting at `cutoff`. /// /// A cutoff of `None` means that there is no cutoff and the @@ -1188,6 +1216,14 @@ impl<'a> StandardPolicy<'a> { self.symmetric_algos.set(s, REJECT); } + /// Considers all symmetric algorithms to be insecure. + /// + /// This is useful when using a good list to determine what + /// algorithms are allowed. + pub fn reject_all_symmetric_algos(&mut self) { + self.symmetric_algos.reject_all(); + } + /// Considers `s` to be insecure starting at `cutoff`. /// /// A cutoff of `None` means that there is no cutoff and the @@ -1233,6 +1269,14 @@ impl<'a> StandardPolicy<'a> { self.aead_algos.set(a, REJECT); } + /// Considers all AEAD algorithms to be insecure. + /// + /// This is useful when using a good list to determine what + /// algorithms are allowed. + pub fn reject_all_aead_algos(&mut self) { + self.aead_algos.reject_all(); + } + /// Considers `a` to be insecure starting at `cutoff`. /// /// A cutoff of `None` means that there is no cutoff and the @@ -1268,6 +1312,14 @@ impl<'a> StandardPolicy<'a> { self.packet_tags.set(tag, REJECT); } + /// Considers all packets to be insecure. + /// + /// This is useful when using a good list to determine what + /// packets are allowed. + pub fn reject_all_packet_tags(&mut self) { + self.packet_tags.reject_all(); + } + /// Start rejecting packets with the given tag at `t`. /// /// A cutoff of `None` means that there is no cutoff and the @@ -2733,4 +2785,118 @@ mod test { assert_eq!(cert.with_policy(p, t).unwrap().keys().count(), 1); Ok(()) } + + #[test] + fn reject_all_hashes() -> Result<()> { + let mut p = StandardPolicy::new(); + + let set_variants = [ + HashAlgorithm::MD5, + HashAlgorithm::Unknown(234), + ]; + let check_variants = [ + HashAlgorithm::SHA512, + HashAlgorithm::Unknown(239), + ]; + + // Accept a few hashes explicitly. + for v in set_variants.iter().cloned() { + p.accept_hash(v); + assert_eq!( + p.hash_cutoff( + v, + HashAlgoSecurity::SecondPreImageResistance), + ACCEPT.map(Into::into)); + assert_eq!( + p.hash_cutoff( + v, + HashAlgoSecurity::CollisionResistance), + ACCEPT.map(Into::into)); + } + + // Reject all hashes. + p.reject_all_hashes(); + + for v in set_variants.iter().chain(check_variants.iter()).cloned() { + p.accept_hash(v); + assert_eq!( + p.hash_cutoff( + v, + HashAlgoSecurity::SecondPreImageResistance), + ACCEPT.map(Into::into)); + assert_eq!( + p.hash_cutoff( + v, + HashAlgoSecurity::CollisionResistance), + ACCEPT.map(Into::into)); + } + + Ok(()) + } + + macro_rules! reject_all_check { + ($reject_all:ident, $accept_one:ident, $cutoff:ident, + $set_variants:expr, $check_variants:expr) => { + #[test] + fn $reject_all() -> Result<()> { + let mut p = StandardPolicy::new(); + + // Accept a few hashes explicitly. + for v in $set_variants.iter().cloned() { + p.$accept_one(v); + assert_eq!(p.$cutoff(v), ACCEPT.map(Into::into)); + } + + // Reject all hashes. + p.$reject_all(); + + for v in $set_variants.iter() + .chain($check_variants.iter()).cloned() + { + assert_eq!( + p.$cutoff(v), + REJECT.map(Into::into)); + } + Ok(()) + } + } + } + + reject_all_check!(reject_all_critical_subpackets, + accept_critical_subpacket, + critical_subpacket_cutoff, + &[ SubpacketTag::TrustSignature, + SubpacketTag::Unknown(252) ], + &[ SubpacketTag::Unknown(253), + SubpacketTag::SignatureCreationTime ]); + + reject_all_check!(reject_all_asymmetric_algos, + accept_asymmetric_algo, + asymmetric_algo_cutoff, + &[ AsymmetricAlgorithm::RSA3072, + AsymmetricAlgorithm::Cv25519 ], + &[ AsymmetricAlgorithm::Unknown, + AsymmetricAlgorithm::NistP256 ]); + + reject_all_check!(reject_all_symmetric_algos, + accept_symmetric_algo, + symmetric_algo_cutoff, + &[ SymmetricAlgorithm::Unencrypted, + SymmetricAlgorithm::Unknown(252) ], + &[ SymmetricAlgorithm::AES256, + SymmetricAlgorithm::Unknown(230) ]); + + reject_all_check!(reject_all_aead_algos, + accept_aead_algo, + aead_algo_cutoff, + &[ AEADAlgorithm::OCB ], + &[ AEADAlgorithm::EAX ]); + + reject_all_check!(reject_all_packet_tags, + accept_packet_tag, + packet_tag_cutoff, + &[ Tag::SEIP, + Tag::Unknown(252) ], + &[ Tag::Signature, + Tag::Unknown(230) ]); } diff --git a/openpgp/src/policy/cutofflist.rs b/openpgp/src/policy/cutofflist.rs index d21d83a5..d745ae7d 100644 --- a/openpgp/src/policy/cutofflist.rs +++ b/openpgp/src/policy/cutofflist.rs @@ -120,7 +120,7 @@ impl<A> Default for CutoffList<A> { impl<A> CutoffList<A> { // Rejects all algorithms. - const fn reject_all() -> Self { + pub(super) const fn reject_all() -> Self { Self { cutoffs: VecOrSlice::empty(), _a: std::marker::PhantomData, @@ -192,6 +192,7 @@ macro_rules! a_cutoff_list { Custom(CutoffList<$algo>), } + #[allow(unused)] impl $name { const DEFAULTS : [ Option<Timestamp>; $values_count ] = $values; @@ -217,6 +218,15 @@ macro_rules! a_cutoff_list { self.force().set(a, cutoff) } + // Reset the cutoff list to its defaults. + fn defaults(&mut self) { + *self = Self::Default(); + } + + fn reject_all(&mut self) { + *self = Self::Custom(CutoffList::reject_all()); + } + fn cutoff(&self, a: $algo) -> Option<Timestamp> { use crate::policy::cutofflist::DEFAULT_POLICY; |