summaryrefslogtreecommitdiffstats
path: root/openpgp/src/policy.rs
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-04-27 14:01:47 +0200
committerJustus Winter <justus@sequoia-pgp.org>2022-04-27 14:15:22 +0200
commit54b82569de73479aad369b4fdd82d7b7be25c988 (patch)
tree4d3c001de8f6aad3d9a646e42019e9f3b6db8c97 /openpgp/src/policy.rs
parent4c06bc409a15e6a9c1157ceefbc4dd9ccaa030e9 (diff)
openpgp: Consider ECDH KDF and KEK parameters in StandardPolicy.
- Previously, there were two issues: - There is an implicit policy that constraints the symmetric algorithm to AES. RFC6637 doesn't forbid other ciphers, so arguably this should be made explicit and moved to the standard policy. Only using AES seems to be a sane default choice and will not impede interoperability in practice (notably, GnuPG constrains to AES as well). - We constrain hashes only based on their output length, and are hence willing to use dubious combinations like (AES128, MD5). - Constrain the parameters in StandardPolicy::key. Mention this in the documentation. - Fixes #839.
Diffstat (limited to 'openpgp/src/policy.rs')
-rw-r--r--openpgp/src/policy.rs48
1 files changed, 47 insertions, 1 deletions
diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs
index 889326c2..20b17162 100644
--- a/openpgp/src/policy.rs
+++ b/openpgp/src/policy.rs
@@ -97,6 +97,12 @@ pub trait Policy : fmt::Debug + Send + Sync {
/// algorithms, don't have a sufficiently high security margin
/// (e.g., 1024-bit RSA keys), are on a bad list, etc. from being
/// used here.
+ ///
+ /// If you implement this function, make sure to consider the Key
+ /// Derivation Function and Key Encapsulation parameters of ECDH
+ /// keys, see [`PublicKey::ECDH`].
+ ///
+ /// [`PublicKey::ECDH`]: crate::crypto::mpi::PublicKey::ECDH
fn key(&self, _ka: &ValidErasedKeyAmalgamation<key::PublicParts>)
-> Result<()>
{
@@ -1417,7 +1423,47 @@ impl<'a> Policy for StandardPolicy<'a> {
let time = self.time.unwrap_or_else(Timestamp::now);
self.asymmetric_algos.check(a, time, None)
- .context("Policy rejected asymmetric algorithm")
+ .context("Policy rejected asymmetric algorithm")?;
+
+ // Check ECDH KDF and KEK parameters.
+ if let PublicKey::ECDH { hash, sym, .. } = ka.mpis() {
+ self.symmetric_algorithm(*sym)
+ .context("Policy rejected ECDH \
+ key encapsulation algorithm")?;
+
+ // RFC6637 says:
+ //
+ // > Refer to Section 13 for the details regarding the
+ // > choice of the KEK algorithm, which SHOULD be one of
+ // > three AES algorithms.
+ //
+ // Furthermore, GnuPG rejects anything other than AES.
+ // I checked the SKS dump, and there are no keys out
+ // there that use a different KEK algorithm.
+ match sym {
+ SymmetricAlgorithm::AES128
+ | SymmetricAlgorithm::AES192
+ | SymmetricAlgorithm::AES256
+ => (), // Good.
+ _ =>
+ return Err(anyhow::Error::from(
+ Error::PolicyViolation(sym.to_string(), None))
+ .context("Policy rejected ECDH \
+ key encapsulation algorithm")),
+ }
+
+ // For use in a KDF the hash algorithm does not
+ // necessarily be collision resistant, but this is the
+ // weakest property that we otherwise care for, so
+ // (somewhat arbitrarily) use this.
+ self
+ .collision_resistant_hash_algos
+ .check(*hash, time, None)
+ .context("Policy rejected ECDH \
+ key derivation hash function")?;
+ }
+
+ Ok(())
}
fn packet(&self, packet: &Packet) -> Result<()> {