diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2022-04-27 14:01:47 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2022-04-27 14:15:22 +0200 |
commit | 54b82569de73479aad369b4fdd82d7b7be25c988 (patch) | |
tree | 4d3c001de8f6aad3d9a646e42019e9f3b6db8c97 /openpgp/src/policy.rs | |
parent | 4c06bc409a15e6a9c1157ceefbc4dd9ccaa030e9 (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.rs | 48 |
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<()> { |