diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-08-22 10:14:47 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2024-06-20 10:58:43 +0200 |
commit | 28a65a7f46e0821da4ce09e334d2993bc272a965 (patch) | |
tree | 0090fe56039d6252966271b39e52b5d23eb56e29 /openpgp/src | |
parent | c475e8060616a84b3b285e6fd99859c1d238a609 (diff) |
openpgp: Implement the PreferredAEADCiphersuites subpacket.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/cert.rs | 27 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation.rs | 7 | ||||
-rw-r--r-- | openpgp/src/packet/signature.rs | 1 | ||||
-rw-r--r-- | openpgp/src/packet/signature/subpacket.rs | 113 | ||||
-rw-r--r-- | openpgp/src/parse.rs | 15 | ||||
-rw-r--r-- | openpgp/src/serialize.rs | 7 |
6 files changed, 136 insertions, 34 deletions
diff --git a/openpgp/src/cert.rs b/openpgp/src/cert.rs index ebc9c8fd..dff91010 100644 --- a/openpgp/src/cert.rs +++ b/openpgp/src/cert.rs @@ -353,6 +353,14 @@ pub trait Preferences<'a>: seal::Sealed { fn preferred_compression_algorithms(&self) -> Option<&'a [CompressionAlgorithm]>; + /// Returns the supported AEAD ciphersuites ordered by preference. + /// + /// The algorithms are ordered according by the certificate holder's + /// preference. + fn preferred_aead_ciphersuites( + &self) + -> Option<&'a [(SymmetricAlgorithm, AEADAlgorithm)]>; + /// Returns the supported AEAD algorithms ordered by preference. /// /// The algorithms are ordered according by the certificate holder's @@ -4442,6 +4450,7 @@ impl<'a> Preferences<'a> for ValidCert<'a> impl_pref!(preferred_symmetric_algorithms, &'a [SymmetricAlgorithm]); impl_pref!(preferred_hash_algorithms, &'a [HashAlgorithm]); impl_pref!(preferred_compression_algorithms, &'a [CompressionAlgorithm]); + impl_pref!(preferred_aead_ciphersuites, &'a [(SymmetricAlgorithm, AEADAlgorithm)]); impl_pref!(preferred_aead_algorithms, &'a [AEADAlgorithm]); impl_pref!(key_server_preferences, KeyServerPreferences); impl_pref!(preferred_key_server, &'a [u8]); @@ -6734,9 +6743,7 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= assert_eq!(userid.preferred_compression_algorithms(), Some(&[ Zlib, BZip2, Zip ][..])); - #[allow(deprecated)] { - assert_eq!(userid.preferred_aead_algorithms(), None); - } + assert_eq!(userid.preferred_aead_ciphersuites(), None); // assert_eq!(userid.key_server_preferences(), // Some(KeyServerPreferences::new(&[]))); @@ -6765,9 +6772,7 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= assert_eq!(userid.preferred_compression_algorithms(), Some(&[ Zlib, BZip2, Zip ][..])); - #[allow(deprecated)] { - assert_eq!(userid.preferred_aead_algorithms(), None); - } + assert_eq!(userid.preferred_aead_ciphersuites(), None); assert_eq!(userid.key_server_preferences(), Some(KeyServerPreferences::new(&[0x80]))); @@ -6785,10 +6790,8 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= cert.preferred_hash_algorithms()); assert_eq!(userid.preferred_compression_algorithms(), cert.preferred_compression_algorithms()); - #[allow(deprecated)] { - assert_eq!(userid.preferred_aead_algorithms(), - cert.preferred_aead_algorithms()); - } + assert_eq!(userid.preferred_aead_ciphersuites(), + cert.preferred_aead_ciphersuites()); assert_eq!(userid.key_server_preferences(), cert.key_server_preferences()); assert_eq!(userid.features(), @@ -6815,9 +6818,7 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= assert_eq!(userid.preferred_compression_algorithms(), Some(&[ BZip2, Zlib, Zip ][..])); - #[allow(deprecated)] { - assert_eq!(userid.preferred_aead_algorithms(), None); - } + assert_eq!(userid.preferred_aead_ciphersuites(), None); assert_eq!(userid.key_server_preferences(), Some(KeyServerPreferences::new(&[0x80]))); diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index f65c588c..c2350974 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -2303,6 +2303,13 @@ impl<'a, C> crate::cert::Preferences<'a> self.map(|s| s.preferred_compression_algorithms()) } + fn preferred_aead_ciphersuites( + &self) + -> Option<&'a [(SymmetricAlgorithm, AEADAlgorithm)]> + { + self.map(|s| s.preferred_aead_ciphersuites()) + } + fn preferred_aead_algorithms(&self) -> Option<&'a [AEADAlgorithm]> { #[allow(deprecated)] self.map(|s| s.preferred_aead_algorithms()) diff --git a/openpgp/src/packet/signature.rs b/openpgp/src/packet/signature.rs index f64c24fd..e6f57ec1 100644 --- a/openpgp/src/packet/signature.rs +++ b/openpgp/src/packet/signature.rs @@ -2578,6 +2578,7 @@ impl crate::packet::Signature { | PreferredAEADAlgorithms | IntendedRecipient | AttestedCertifications + | PreferredAEADCiphersuites | Reserved(_) => false, Issuer diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs index 6d775660..1b16d700 100644 --- a/openpgp/src/packet/signature/subpacket.rs +++ b/openpgp/src/packet/signature/subpacket.rs @@ -326,6 +326,27 @@ pub enum SubpacketTag { /// /// [Section 5.2.3.30 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10.html#section-5.2.3.30 AttestedCertifications, + + /// The AEAD Ciphersuites that the certificate holder prefers. + /// + /// A series of paired algorithm identifiers indicating how the + /// keyholder prefers to receive version 2 Symmetrically Encrypted + /// Integrity Protected Data. Each pair of octets indicates a + /// combination of a symmetric cipher and an AEAD mode that the + /// key holder prefers to use. + /// + /// It is assumed that only the combinations of algorithms listed + /// are supported by the recipient's software, with the exception + /// of the mandatory-to-implement combination of AES-128 and OCB. + /// If AES-128 and OCB are not found in the subpacket, it is + /// implicitly listed at the end. + /// + /// See [Section 5.2.3.15 of draft-ietf-openpgp-crypto-refresh-10] + /// for details. + /// + /// [Section 5.2.3.15 of draft-ietf-openpgp-crypto-refresh-10]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-preferred-aead-ciphersuites + PreferredAEADCiphersuites, + /// Reserved subpacket tag. Reserved(u8), /// Private subpacket tag. @@ -376,6 +397,7 @@ impl From<u8> for SubpacketTag { 34 => SubpacketTag::PreferredAEADAlgorithms, 35 => SubpacketTag::IntendedRecipient, 37 => SubpacketTag::AttestedCertifications, + 39 => SubpacketTag::PreferredAEADCiphersuites, 0| 1| 8| 13| 14| 15| 17| 18| 19 | 38 => SubpacketTag::Reserved(u), 100..=110 => SubpacketTag::Private(u), _ => SubpacketTag::Unknown(u), @@ -415,6 +437,7 @@ impl From<SubpacketTag> for u8 { SubpacketTag::PreferredAEADAlgorithms => 34, SubpacketTag::IntendedRecipient => 35, SubpacketTag::AttestedCertifications => 37, + SubpacketTag::PreferredAEADCiphersuites => 39, SubpacketTag::Reserved(u) => u, SubpacketTag::Private(u) => u, SubpacketTag::Unknown(u) => u, @@ -423,7 +446,7 @@ impl From<SubpacketTag> for u8 { } #[allow(deprecated)] -const SUBPACKET_TAG_VARIANTS: [SubpacketTag; 28] = [ +const SUBPACKET_TAG_VARIANTS: [SubpacketTag; 29] = [ SubpacketTag::SignatureCreationTime, SubpacketTag::SignatureExpirationTime, SubpacketTag::ExportableCertification, @@ -452,6 +475,7 @@ const SUBPACKET_TAG_VARIANTS: [SubpacketTag; 28] = [ SubpacketTag::PreferredAEADAlgorithms, SubpacketTag::IntendedRecipient, SubpacketTag::AttestedCertifications, + SubpacketTag::PreferredAEADCiphersuites, ]; impl SubpacketTag { @@ -1696,6 +1720,26 @@ pub enum SubpacketValue { /// /// [Section 5.2.3.30 of RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-10.html#section-5.2.3.30 AttestedCertifications(Vec<Box<[u8]>>), + + /// The AEAD Ciphersuites that the certificate holder prefers. + /// + /// A series of paired algorithm identifiers indicating how the + /// keyholder prefers to receive version 2 Symmetrically Encrypted + /// Integrity Protected Data. Each pair of octets indicates a + /// combination of a symmetric cipher and an AEAD mode that the + /// key holder prefers to use. + /// + /// It is assumed that only the combinations of algorithms listed + /// are supported by the recipient's software, with the exception + /// of the mandatory-to-implement combination of AES-128 and OCB. + /// If AES-128 and OCB are not found in the subpacket, it is + /// implicitly listed at the end. + /// + /// See [Section 5.2.3.15 of draft-ietf-openpgp-crypto-refresh-10] + /// for details. + /// + /// [Section 5.2.3.15 of draft-ietf-openpgp-crypto-refresh-10]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-preferred-aead-ciphersuites + PreferredAEADCiphersuites(Vec<(SymmetricAlgorithm, AEADAlgorithm)>), } assert_send_and_sync!(SubpacketValue); @@ -1707,7 +1751,7 @@ impl ArbitraryBounded for SubpacketValue { loop { #[allow(deprecated)] - break match gen_arbitrary_from_range(0..26, g) { + break match gen_arbitrary_from_range(0..27, g) { 0 => SignatureCreationTime(Arbitrary::arbitrary(g)), 1 => SignatureExpirationTime(Arbitrary::arbitrary(g)), 2 => ExportableCertification(Arbitrary::arbitrary(g)), @@ -1746,6 +1790,7 @@ impl ArbitraryBounded for SubpacketValue { 23 => IssuerFingerprint(Arbitrary::arbitrary(g)), 24 => PreferredAEADAlgorithms(Arbitrary::arbitrary(g)), 25 => IntendedRecipient(Arbitrary::arbitrary(g)), + 26 => PreferredAEADCiphersuites(Arbitrary::arbitrary(g)), _ => unreachable!(), } } @@ -1794,6 +1839,8 @@ impl SubpacketValue { SubpacketTag::PreferredAEADAlgorithms, IntendedRecipient(_) => SubpacketTag::IntendedRecipient, AttestedCertifications(_) => SubpacketTag::AttestedCertifications, + PreferredAEADCiphersuites(_) => + SubpacketTag::PreferredAEADCiphersuites, Unknown { tag, .. } => *tag, } } @@ -3271,18 +3318,16 @@ impl SubpacketAreas { } } - /// Returns the value of the Preferred AEAD Algorithms subpacket. + /// Returns the value of the Preferred AEAD Ciphersuites subpacket. /// - /// The [Preferred AEAD Algorithms subpacket] indicates what AEAD - /// algorithms the key holder prefers ordered by preference. If - /// this is set, then the AEAD feature flag should in the + /// The [Preferred AEAD Ciphersuites subpacket] indicates what + /// AEAD ciphersuites (i.e. pairs of symmetric algorithm and AEAD + /// algorithm) the key holder prefers ordered by preference. If + /// this is set, then the SEIPDv2 feature flag should in the /// [Features subpacket] should also be set. /// - /// Note: because support for AEAD has not yet been standardized, - /// we recommend not yet advertising support for it. - /// - /// [Preferred AEAD Algorithms subpacket]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.8 - /// [Features subpacket]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.25 + /// [Preferred AEAD Ciphersuites subpacket]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-preferred-aead-ciphersuites + /// [Features subpacket]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#features-subpacket /// /// This subpacket is a type of preference. When looking up a /// preference, an OpenPGP implementation should first look for @@ -3306,7 +3351,25 @@ impl SubpacketAreas { /// Note: if the signature contains multiple instances of this /// subpacket in the hashed subpacket area, the last one is /// returned. - #[deprecated] + pub fn preferred_aead_ciphersuites(&self) + -> Option<&[(SymmetricAlgorithm, AEADAlgorithm)]> + { + if let Some(sb) = self.subpacket( + SubpacketTag::PreferredAEADCiphersuites) + { + if let SubpacketValue::PreferredAEADCiphersuites(v) + = &sb.value + { + Some(v) + } else { + None + } + } else { + None + } + } + + /// Returns the value of the Preferred AEAD Algorithms subpacket. pub fn preferred_aead_algorithms(&self) -> Option<&[AEADAlgorithm]> { // array of one-octet values @@ -6966,7 +7029,19 @@ impl signature::SignatureBuilder { /// # Ok(()) /// # } /// ``` - #[deprecated] + pub fn set_preferred_aead_ciphersuites( + mut self, + preferences: Vec<(SymmetricAlgorithm, AEADAlgorithm)>) + -> Result<Self> + { + self.hashed_area.replace(Subpacket::new( + SubpacketValue::PreferredAEADCiphersuites(preferences), + false)?)?; + + Ok(self) + } + + /// Sets the Preferred AEAD Algorithms subpacket. pub fn set_preferred_aead_algorithms(mut self, preferences: Vec<AEADAlgorithm>) -> Result<Self> @@ -7409,16 +7484,12 @@ fn accessors() { assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(), vec![ &fp ]); - let pref = vec![AEADAlgorithm::EAX, - AEADAlgorithm::OCB]; - #[allow(deprecated)] { - sig = sig.set_preferred_aead_algorithms(pref.clone()).unwrap(); - } + let pref = vec![(SymmetricAlgorithm::AES128, AEADAlgorithm::EAX), + (SymmetricAlgorithm::AES128, AEADAlgorithm::OCB)]; + sig = sig.set_preferred_aead_ciphersuites(pref.clone()).unwrap(); let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap(); - #[allow(deprecated)] { - assert_eq!(sig_.preferred_aead_algorithms(), Some(&pref[..])); - } + assert_eq!(sig_.preferred_aead_ciphersuites(), Some(&pref[..])); let fps = vec![ Fingerprint::from_bytes(b"aaaaaaaaaaaaaaaaaaaa"), diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs index 2f05541c..702b1fa0 100644 --- a/openpgp/src/parse.rs +++ b/openpgp/src/parse.rs @@ -1862,6 +1862,21 @@ impl Subpacket { bytes.chunks(digest_size).map(Into::into).collect()) } }, + + SubpacketTag::PreferredAEADCiphersuites => { + if len % 2 != 0 { + return Err(Error::BadSignature( + "Wrong number of bytes in preferred AEAD \ + Ciphersuites subpacket" + .into()).into()); + } + + SubpacketValue::PreferredAEADCiphersuites( + php.parse_bytes("pref aead ciphersuites", len)? + .chunks(2).map(|o| (o[0].into(), + o[1].into())).collect()) + }, + SubpacketTag::Reserved(_) | SubpacketTag::PlaceholderForBackwardCompatibility | SubpacketTag::Private(_) diff --git a/openpgp/src/serialize.rs b/openpgp/src/serialize.rs index 7927dce0..b179d617 100644 --- a/openpgp/src/serialize.rs +++ b/openpgp/src/serialize.rs @@ -1529,6 +1529,12 @@ impl Marshal for SubpacketValue { o.write_all(digest)?; } }, + + PreferredAEADCiphersuites(p) => + for (symm, aead) in p { + o.write_all(&[(*symm).into(), (*aead).into()])?; + }, + Unknown { body, .. } => o.write_all(body)?, } @@ -1571,6 +1577,7 @@ impl MarshalInto for SubpacketValue { 1 + (fp as &dyn MarshalInto).serialized_len(), AttestedCertifications(digests) => digests.iter().map(|d| d.len()).sum(), + PreferredAEADCiphersuites(c) => c.len() * 2, Unknown { body, .. } => body.len(), } } |