Skip to main content

pgp/packet/signature/
types.rs

1use std::{
2    cmp::Ordering,
3    io::{BufRead, Read},
4};
5
6use bitfields::bitfield;
7use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
8use bytes::Bytes;
9use digest::DynDigest;
10use log::debug;
11use num_enum::{FromPrimitive, IntoPrimitive};
12
13use crate::{
14    crypto::{
15        aead::AeadAlgorithm,
16        hash::{HashAlgorithm, WriteHasher},
17        public_key::PublicKeyAlgorithm,
18        sym::SymmetricKeyAlgorithm,
19    },
20    errors::{bail, ensure, ensure_eq, unimplemented_err, unsupported_err, Result},
21    line_writer::LineBreak,
22    normalize_lines::NormalizedReader,
23    packet::{
24        signature::SignatureConfig, PacketHeader, PacketTrait, SignatureVersionSpecific, Subpacket,
25        SubpacketData,
26    },
27    parsing::BufParsing,
28    parsing_reader::BufReadParsing,
29    ser::Serialize,
30    types::{
31        self, CompressionAlgorithm, Duration, Fingerprint, KeyDetails, KeyId, KeyVersion,
32        PacketLength, SignatureBytes, Tag, Timestamp, VerifyingKey,
33    },
34};
35
36/// Signature Packet
37///
38/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-signature-packet-type-id-2>
39///
40/// OpenPGP Signatures are a very generic mechanism. They are always used by a signer to make a
41/// statement about some data payload, and the [`SignatureConfig`] metadata of the signature packet.
42/// The statement can be verified by anyone with access to the signer's public key, the payload
43/// data, and the signature packet.
44///
45/// Signature packets are used in two very distinct contexts:
46///
47/// - As **data signatures** (either inline, in OpenPGP Messages, or as detached signatures
48///   over standalone data files).
49/// - As **certificate-forming signatures** (e.g. to bind a subkey to a primary key).
50///
51/// For data signatures, the signer's intended statement is usually either "I am the author of
52/// this payload" (e.g. for an email), or "I confirm that this payload has been handled
53/// appropriately" (e.g. to signal that a software package has been built by the infrastructure of
54/// a Linux distribution).
55///
56/// For certificate-forming signatures, typical statements of signature packets are "the primary
57/// key holder wants to associate this subkey with the primary", or "the key holder wants to
58/// associate this identity (e.g. an email address) with their primary key".
59/// Third-party signatures can be used by third parties to make statements, e.g. that they have
60/// verified that an identity is validly associated with a key (such as: "I have verified that this
61/// key belongs to Alice").
62///
63/// The purpose of a signature packet is marked by its [`SignatureType`].
64#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
65pub struct Signature {
66    packet_header: PacketHeader,
67    pub(crate) inner: InnerSignature,
68}
69
70#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
71pub(crate) enum InnerSignature {
72    /// V2, V3, V4 and V6
73    Known {
74        config: SignatureConfig,
75        #[debug("{}", hex::encode(signed_hash_value))]
76        signed_hash_value: [u8; 2],
77        signature: SignatureBytes,
78    },
79    Unknown {
80        version: SignatureVersion,
81        #[debug("{}", hex::encode(data))]
82        data: Bytes,
83    },
84}
85
86impl Signature {
87    /// Constructor for an OpenPGP v2 signature packet.
88    /// Note: This is a historical packet version!
89    #[allow(clippy::too_many_arguments)]
90    pub fn v2(
91        packet_header: PacketHeader,
92        typ: SignatureType,
93        pub_alg: PublicKeyAlgorithm,
94        hash_alg: HashAlgorithm,
95        created: Timestamp,
96        issuer_key_id: KeyId,
97        signed_hash_value: [u8; 2],
98        signature: SignatureBytes,
99    ) -> Self {
100        Signature {
101            packet_header,
102            inner: InnerSignature::Known {
103                config: SignatureConfig {
104                    typ,
105                    pub_alg,
106                    hash_alg,
107                    hashed_subpackets: vec![],
108                    unhashed_subpackets: vec![],
109                    version_specific: SignatureVersionSpecific::V2 {
110                        created,
111                        issuer_key_id,
112                    },
113                },
114                signed_hash_value,
115                signature,
116            },
117        }
118    }
119
120    /// Constructor for an OpenPGP v3 signature packet.
121    /// Note: This is a historical packet version!
122    #[allow(clippy::too_many_arguments)]
123    pub fn v3(
124        packet_header: PacketHeader,
125        typ: SignatureType,
126        pub_alg: PublicKeyAlgorithm,
127        hash_alg: HashAlgorithm,
128        created: Timestamp,
129        issuer_key_id: KeyId,
130        signed_hash_value: [u8; 2],
131        signature: SignatureBytes,
132    ) -> Self {
133        Signature {
134            packet_header,
135            inner: InnerSignature::Known {
136                config: SignatureConfig {
137                    typ,
138                    pub_alg,
139                    hash_alg,
140                    hashed_subpackets: vec![],
141                    unhashed_subpackets: vec![],
142                    version_specific: SignatureVersionSpecific::V3 {
143                        created,
144                        issuer_key_id,
145                    },
146                },
147                signed_hash_value,
148                signature,
149            },
150        }
151    }
152
153    /// Constructor for an OpenPGP v4 signature packet.
154    ///
155    /// OpenPGP v4 signatures are typically used with OpenPGP v4 keys, as specified in RFC 9580
156    /// (and formerly in 4880 and 2440).
157    #[allow(clippy::too_many_arguments)]
158    pub fn v4(
159        packet_header: PacketHeader,
160        typ: SignatureType,
161        pub_alg: PublicKeyAlgorithm,
162        hash_alg: HashAlgorithm,
163        signed_hash_value: [u8; 2],
164        signature: SignatureBytes,
165        hashed_subpackets: Vec<Subpacket>,
166        unhashed_subpackets: Vec<Subpacket>,
167    ) -> Self {
168        Signature {
169            packet_header,
170            inner: InnerSignature::Known {
171                config: SignatureConfig {
172                    typ,
173                    pub_alg,
174                    hash_alg,
175                    hashed_subpackets,
176                    unhashed_subpackets,
177                    version_specific: SignatureVersionSpecific::V4,
178                },
179                signed_hash_value,
180                signature,
181            },
182        }
183    }
184
185    /// Constructor for an OpenPGP v6 signature packet.
186    ///
187    /// OpenPGP v6 signatures are specified in RFC 9580 and only used with OpenPGP v6 keys.
188    #[allow(clippy::too_many_arguments)]
189    pub fn v6(
190        packet_header: PacketHeader,
191        typ: SignatureType,
192        pub_alg: PublicKeyAlgorithm,
193        hash_alg: HashAlgorithm,
194        signed_hash_value: [u8; 2],
195        signature: SignatureBytes,
196        hashed_subpackets: Vec<Subpacket>,
197        unhashed_subpackets: Vec<Subpacket>,
198        salt: Vec<u8>,
199    ) -> Self {
200        Signature {
201            packet_header,
202            inner: InnerSignature::Known {
203                config: SignatureConfig {
204                    typ,
205                    pub_alg,
206                    hash_alg,
207                    hashed_subpackets,
208                    unhashed_subpackets,
209                    version_specific: SignatureVersionSpecific::V6 { salt },
210                },
211                signed_hash_value,
212                signature,
213            },
214        }
215    }
216
217    /// Create a signature of unknown version
218    pub fn unknown(packet_header: PacketHeader, version: SignatureVersion, data: Bytes) -> Self {
219        Self {
220            packet_header,
221            inner: InnerSignature::Unknown { version, data },
222        }
223    }
224
225    pub fn from_config(
226        config: SignatureConfig,
227        signed_hash_value: [u8; 2],
228        signature: SignatureBytes,
229    ) -> Result<Self> {
230        let len = match config.version() {
231            SignatureVersion::V2 | SignatureVersion::V3 => {
232                let mut sum = 1;
233                sum += config.write_len_v3();
234                sum += 2; // signed hash value
235                sum += signature.write_len();
236                sum
237            }
238            SignatureVersion::V4 | SignatureVersion::V6 => {
239                let mut sum = 1;
240                sum += config.write_len_v4_v6();
241                sum += 2; // signed hash value
242                if let SignatureVersionSpecific::V6 { ref salt } = config.version_specific {
243                    sum += 1;
244                    sum += salt.len();
245                }
246                sum += signature.write_len();
247                sum
248            }
249            SignatureVersion::V5 => {
250                unsupported_err!("crate V5 signature")
251            }
252            SignatureVersion::Other(version) => unsupported_err!("signature version {}", version),
253        };
254        let packet_header = PacketHeader::new_fixed(Tag::Signature, len.try_into()?);
255
256        Ok(Signature {
257            packet_header,
258            inner: InnerSignature::Known {
259                config,
260                signed_hash_value,
261                signature,
262            },
263        })
264    }
265
266    /// Returns the `SignatureConfig` if this is a known signature format.
267    pub fn config(&self) -> Option<&SignatureConfig> {
268        match self.inner {
269            InnerSignature::Known { ref config, .. } => Some(config),
270            InnerSignature::Unknown { .. } => None,
271        }
272    }
273
274    /// Appends a subpacket at the back of the unhashed area
275    pub fn unhashed_subpacket_push(&mut self, subpacket: Subpacket) -> Result<()> {
276        if let InnerSignature::Known { ref config, .. } = self.inner {
277            self.unhashed_subpacket_insert(config.unhashed_subpackets.len(), subpacket)
278        } else {
279            bail!("Unknown Signature type, can't add Subpacket");
280        }
281    }
282
283    /// Insert a subpacket into the unhashed area at position `index`, shifting all subpackets
284    /// after it to the right
285    pub fn unhashed_subpacket_insert(&mut self, index: usize, subpacket: Subpacket) -> Result<()> {
286        if let InnerSignature::Known { ref mut config, .. } = self.inner {
287            if let PacketLength::Fixed(packetlen) = self.packet_header.packet_length_mut() {
288                ensure!(
289                    // `<=`, because index may point to the entry *after* the last element
290                    index <= config.unhashed_subpackets.len(),
291                    "Index {} is larger than the unhashed subpacket area",
292                    index
293                );
294
295                let len = u32::try_from(subpacket.write_len())?;
296
297                config.unhashed_subpackets.insert(index, subpacket);
298                *packetlen += len;
299            } else {
300                bail!(
301                    "Unexpected PacketLength encoding {:?}, can't modify the unhashed area",
302                    self.packet_header.packet_length()
303                );
304            }
305
306            Ok(())
307        } else {
308            bail!("Unknown Signature type, can't add Subpacket");
309        }
310    }
311
312    /// Removes and returns the unhashed subpacket at position `index`, shifting all other
313    /// unhashed subpackets to the left
314    pub fn unhashed_subpacket_remove(&mut self, index: usize) -> Result<Subpacket> {
315        if let InnerSignature::Known { ref mut config, .. } = self.inner {
316            ensure!(
317                // `<`, because index must point at45 an existing element
318                index < config.unhashed_subpackets.len(),
319                "Index {} is not contained in the unhashed subpacket area",
320                index
321            );
322
323            if let PacketLength::Fixed(packetlen) = self.packet_header.packet_length_mut() {
324                let sp = config.unhashed_subpackets.remove(index);
325                *packetlen -= u32::try_from(sp.write_len())?;
326                Ok(sp)
327            } else {
328                bail!(
329                    "Unexpected PacketLength encoding {:?}, can't modify the unhashed area",
330                    self.packet_header.packet_length()
331                );
332            }
333        } else {
334            bail!("Unknown Signature type, can't remove Subpacket");
335        }
336    }
337
338    /// Sorts the subpackets in the unhashed area with a comparison function,
339    /// preserving initial order of equal elements.
340    pub fn unhashed_subpackets_sort_by<F>(&mut self, compare: F)
341    where
342        F: FnMut(&Subpacket, &Subpacket) -> Ordering,
343    {
344        if let InnerSignature::Known { ref mut config, .. } = self.inner {
345            config.unhashed_subpackets.sort_by(compare);
346        }
347    }
348
349    /// Returns the `SignatureVersion`.
350    pub fn version(&self) -> SignatureVersion {
351        match self.inner {
352            InnerSignature::Known { ref config, .. } => config.version(),
353            InnerSignature::Unknown { version, .. } => version,
354        }
355    }
356
357    /// Returns what kind of signature this is.
358    pub fn typ(&self) -> Option<SignatureType> {
359        self.config().map(|c| c.typ())
360    }
361
362    /// The used `HashAlgorithm`.
363    pub fn hash_alg(&self) -> Option<HashAlgorithm> {
364        self.config().map(|c| c.hash_alg)
365    }
366
367    /// Returns the actual byte level signature.
368    pub fn signature(&self) -> Option<&SignatureBytes> {
369        match self.inner {
370            InnerSignature::Known { ref signature, .. } => Some(signature),
371            InnerSignature::Unknown { .. } => None,
372        }
373    }
374
375    pub fn signed_hash_value(&self) -> Option<[u8; 2]> {
376        match self.inner {
377            InnerSignature::Known {
378                signed_hash_value, ..
379            } => Some(signed_hash_value),
380            InnerSignature::Unknown { .. } => None,
381        }
382    }
383
384    /// Does `key` match any issuer or issuer_fingerprint subpacket in `sig`?
385    /// If yes, we consider `key` a candidate to verify `sig` against.
386    ///
387    /// We also consider `key` a match for `sig` by default, if `sig` contains no issuer-related
388    /// subpackets.
389    fn match_identity(sig: &Signature, key: &impl KeyDetails) -> bool {
390        let issuer_key_ids = sig.issuer_key_id();
391        let issuer_fps = sig.issuer_fingerprint();
392
393        // If there is no subpacket that signals the issuer, we consider `sig` and `key` a
394        // potential match, and will check the cryptographic validity.
395        if issuer_key_ids.is_empty() && issuer_fps.is_empty() {
396            return true;
397        }
398
399        // Does any issuer or issuer fingerprint subpacket matche the identity of `sig`?
400        issuer_key_ids
401            .iter()
402            .any(|&key_id| key_id == &key.legacy_key_id())
403            || issuer_fps.iter().any(|&fp| fp == &key.fingerprint())
404    }
405
406    /// Check alignment between signing key version and signature version.
407    ///
408    /// Version 6 signatures and version 6 keys are strongly linked:
409    /// - only a v6 key may produce a v6 signature
410    /// - a v6 key may only produce v6 signatures
411    fn check_signature_key_version_alignment(
412        key: &impl KeyDetails,
413        config: &SignatureConfig,
414    ) -> Result<()> {
415        // Every signature made by a version 6 key MUST be a version 6 signature.
416        if key.version() == KeyVersion::V6 {
417            ensure_eq!(
418                config.version(),
419                SignatureVersion::V6,
420                "Non v6 signature by a v6 key is not allowed"
421            );
422        }
423
424        if config.version() == SignatureVersion::V6 {
425            ensure_eq!(
426                key.version(),
427                KeyVersion::V6,
428                "v6 signature by a non-v6 key is not allowed"
429            );
430        }
431
432        Ok(())
433    }
434
435    /// Check if the hash algorithm is acceptable for the signature configuration
436    /// (in particular, if it's allowed in combination with the public key algorithm).
437    pub(crate) fn check_signature_hash_strength(config: &SignatureConfig) -> Result<()> {
438        if config.pub_alg.is_pqc() {
439            // For all signature algorithms in draft-ietf-openpgp-pqc-10,
440            // hash digest sizes of at least 256 bits are required:
441            //
442            // https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#name-signature-packet-tag-2
443            // https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#name-signature-packet-tag-2-2
444
445            let Some(digest_size) = config.hash_alg.digest_size() else {
446                bail!("Illegal hash_alg setting {}", config.hash_alg);
447            };
448
449            ensure!(
450                digest_size * 8 >= 256,
451                "PQC signatures must use hash algorithms with digest size >= 256 bits, {} is insufficient",
452                config.hash_alg
453            );
454        }
455
456        Ok(())
457    }
458
459    /// Verify this signature.
460    pub fn verify<R>(&self, key: &impl VerifyingKey, data: R) -> Result<()>
461    where
462        R: Read,
463    {
464        let InnerSignature::Known {
465            ref config,
466            ref signed_hash_value,
467            ref signature,
468        } = self.inner
469        else {
470            unsupported_err!("signature version {:?}", self.version());
471        };
472
473        Self::check_signature_key_version_alignment(&key, config)?;
474        Self::check_signature_hash_strength(config)?;
475
476        ensure!(
477            Self::match_identity(self, key),
478            "verify: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
479            &key.legacy_key_id(),
480        );
481
482        let mut hasher = config.hash_alg.new_hasher()?;
483
484        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
485            // Salt size must match the expected length for the hash algorithm that is used
486            //
487            // See: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3-2.10.2.1.1
488            ensure_eq!(
489                config.hash_alg.salt_len(),
490                Some(salt.len()),
491                "Illegal salt length {} for a V6 Signature using {:?}",
492                salt.len(),
493                config.hash_alg
494            );
495
496            hasher.update(salt.as_ref())
497        }
498
499        if matches!(self.typ(), Some(SignatureType::Text)) {
500            let normalized = NormalizedReader::new(data, LineBreak::Crlf);
501
502            config.hash_data_to_sign(&mut hasher, normalized)?;
503        } else {
504            config.hash_data_to_sign(&mut hasher, data)?;
505        }
506        let len = config.hash_signature_data(&mut hasher)?;
507        hasher.update(&config.trailer(len)?);
508
509        let hash = &hasher.finalize()[..];
510
511        // Check that the high 16 bits of the hash from the signature packet match with the hash we
512        // just calculated.
513        //
514        // "When verifying a version 6 signature, an implementation MUST reject the signature if
515        // these octets do not match the first two octets of the computed hash."
516        //
517        // (See https://www.rfc-editor.org/rfc/rfc9580.html#name-notes-on-signatures)
518        //
519        // (Note: we currently also reject v4 signatures if the calculated hash doesn't match the
520        // high 16 bits in the signature packet, even though RFC 9580 doesn't strictly require this)
521        ensure_eq!(
522            signed_hash_value,
523            &hash[0..2],
524            "signature: invalid signed hash value"
525        );
526
527        key.verify(config.hash_alg, hash, signature)
528    }
529
530    /// Verifies a certification signature type (for self-signatures).
531    pub fn verify_certification<V>(&self, key: &V, tag: Tag, id: &impl Serialize) -> Result<()>
532    where
533        V: VerifyingKey + Serialize,
534    {
535        self.verify_third_party_certification(&key, &key, tag, id)
536    }
537
538    /// Verifies a certification signature type (for third-party signatures).
539    pub fn verify_third_party_certification<V, K>(
540        &self,
541        signee: &K,
542        signer: &V,
543        tag: Tag,
544        id: &impl Serialize,
545    ) -> Result<()>
546    where
547        V: VerifyingKey + Serialize,
548        K: KeyDetails + Serialize,
549    {
550        let InnerSignature::Known {
551            ref config,
552            ref signed_hash_value,
553            ref signature,
554        } = self.inner
555        else {
556            unsupported_err!("signature version {:?}", self.version());
557        };
558        let key_id = signee.legacy_key_id();
559        debug!("verifying certification {key_id:?} {self:#?}");
560
561        Self::check_signature_key_version_alignment(&signer, config)?;
562        Self::check_signature_hash_strength(config)?;
563
564        ensure!(
565            Self::match_identity(self, signer),
566            "verify_certification: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
567            key_id,
568        );
569
570        let mut hasher = config.hash_alg.new_hasher()?;
571
572        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
573            hasher.update(salt.as_ref())
574        }
575
576        // the key of the signee
577        {
578            // TODO: this is different for V5
579            serialize_for_hashing(signee, &mut hasher)?;
580        }
581
582        // the packet content
583        {
584            let packet_len = id.write_len();
585
586            match config.version() {
587                SignatureVersion::V2 | SignatureVersion::V3 => {
588                    // Nothing to do
589                }
590                SignatureVersion::V4 | SignatureVersion::V6 => {
591                    let prefix = match tag {
592                        Tag::UserId => 0xB4,
593                        Tag::UserAttribute => 0xD1,
594                        _ => bail!("invalid tag for certification validation: {:?}", tag),
595                    };
596
597                    let mut prefix_buf = [prefix, 0u8, 0u8, 0u8, 0u8];
598                    BigEndian::write_u32(&mut prefix_buf[1..], packet_len.try_into()?);
599
600                    // prefixes
601                    hasher.update(&prefix_buf);
602                }
603                SignatureVersion::V5 => {
604                    bail!("v5 signature unsupported tpc")
605                }
606                SignatureVersion::Other(version) => {
607                    bail!("unsupported signature version: {:?}", version)
608                }
609            }
610
611            id.to_writer(&mut WriteHasher(&mut hasher))?;
612        }
613
614        let len = config.hash_signature_data(&mut hasher)?;
615        hasher.update(&config.trailer(len)?);
616
617        let hash = &hasher.finalize()[..];
618        ensure_eq!(
619            signed_hash_value,
620            &hash[0..2],
621            "certification: invalid signed hash value"
622        );
623
624        signer.verify(config.hash_alg, hash, signature)
625    }
626
627    /// Verifies a subkey binding (which binds a subkey to the primary key).
628    ///
629    /// The primary key is expected as `signer`, the subkey as `signee`.
630    ///
631    /// "Subkey Binding Signature (type ID 0x18)"
632    pub fn verify_subkey_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
633    where
634        V: VerifyingKey + Serialize,
635        K: KeyDetails + Serialize,
636    {
637        debug!("verifying subkey binding: {self:#?} - {signer:#?} - {signee:#?}",);
638
639        let InnerSignature::Known {
640            ref config,
641            ref signed_hash_value,
642            ref signature,
643        } = self.inner
644        else {
645            unsupported_err!("signature version {:?}", self.version());
646        };
647
648        Self::check_signature_key_version_alignment(&signer, config)?;
649        Self::check_signature_hash_strength(config)?;
650
651        let mut hasher = config.hash_alg.new_hasher()?;
652
653        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
654            hasher.update(salt.as_ref())
655        }
656
657        serialize_for_hashing(signer, &mut hasher)?; // primary
658        serialize_for_hashing(signee, &mut hasher)?; // subkey
659
660        let len = config.hash_signature_data(&mut hasher)?;
661        hasher.update(&config.trailer(len)?);
662
663        let hash = &hasher.finalize()[..];
664        ensure_eq!(
665            signed_hash_value,
666            &hash[0..2],
667            "subkey binding: invalid signed hash value"
668        );
669
670        signer.verify(config.hash_alg, hash, signature)
671    }
672
673    /// Verifies a primary key binding signature, or "back signature" (which links the primary to a signing subkey).
674    ///
675    /// The subkey is expected as `signer`, the primary key as `signee`.
676    ///
677    /// "Primary Key Binding Signature (type ID 0x19)"
678    pub fn verify_primary_key_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
679    where
680        V: VerifyingKey + Serialize,
681        K: KeyDetails + Serialize,
682    {
683        debug!("verifying primary key binding: {self:#?} - {signer:#?} - {signee:#?}");
684
685        let InnerSignature::Known {
686            ref config,
687            ref signed_hash_value,
688            ref signature,
689        } = self.inner
690        else {
691            unsupported_err!("signature version {:?}", self.version());
692        };
693
694        Self::check_signature_key_version_alignment(&signer, config)?;
695        Self::check_signature_hash_strength(config)?;
696
697        let mut hasher = config.hash_alg.new_hasher()?;
698
699        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
700            hasher.update(salt.as_ref())
701        }
702
703        serialize_for_hashing(signee, &mut hasher)?; // primary
704        serialize_for_hashing(signer, &mut hasher)?; // subkey
705
706        let len = config.hash_signature_data(&mut hasher)?;
707        hasher.update(&config.trailer(len)?);
708
709        let hash = &hasher.finalize()[..];
710        ensure_eq!(
711            signed_hash_value,
712            &hash[0..2],
713            "key binding: invalid signed hash value"
714        );
715
716        signer.verify(config.hash_alg, hash, signature)
717    }
718
719    /// Verifies a direct key signature or a revocation.
720    pub fn verify_key<V>(&self, key: &V) -> Result<()>
721    where
722        V: VerifyingKey + Serialize,
723    {
724        self.verify_key_third_party(key, key)
725    }
726
727    /// Verifies a third-party direct key signature or a revocation.
728    pub fn verify_key_third_party<V, K>(&self, signee: &K, signer: &V) -> Result<()>
729    where
730        V: VerifyingKey + Serialize,
731        K: KeyDetails + Serialize,
732    {
733        debug!("verifying direct signature: {self:#?} - signer {signer:#?}, signee {signee:#?}");
734
735        let InnerSignature::Known {
736            ref config,
737            ref signed_hash_value,
738            ref signature,
739        } = self.inner
740        else {
741            unsupported_err!("signature version {:?}", self.version());
742        };
743        Self::check_signature_key_version_alignment(&signer, config)?;
744        Self::check_signature_hash_strength(config)?;
745
746        ensure!(
747            Self::match_identity(self, signer),
748            "verify_key: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
749            &signer.legacy_key_id(),
750        );
751
752        let mut hasher = config.hash_alg.new_hasher()?;
753
754        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
755            hasher.update(salt.as_ref())
756        }
757
758        serialize_for_hashing(signee, &mut hasher)?;
759
760        let len = config.hash_signature_data(&mut hasher)?;
761        hasher.update(&config.trailer(len)?);
762
763        let hash = &hasher.finalize()[..];
764        ensure_eq!(
765            signed_hash_value,
766            &hash[0..2],
767            "key: invalid signed hash value"
768        );
769
770        signer.verify(config.hash_alg, hash, signature)
771    }
772
773    /// Returns if the signature is a certification or not.
774    pub fn is_certification(&self) -> bool {
775        self.config()
776            .map(|c| c.is_certification())
777            .unwrap_or_default()
778    }
779
780    /// If the hashed area contains any KeyExpirationTime subpacket, then this
781    /// returns `Some(Duration)` of the first KeyExpirationTime subpacket encountered.
782    ///
783    /// If the hashed area contains no KeyExpirationTime subpacket, this returns `None`.
784    ///
785    /// (Note that a return value of `Some(Duration(0))` also means that no key expiration time
786    /// applies to the target component. This corresponds to a different wire-format
787    /// representation, but is semantically equivalent to `None`.)
788    pub fn key_expiration_time(&self) -> Option<Duration> {
789        self.config().and_then(|h| {
790            h.hashed_subpackets().find_map(|p| match &p.data {
791                SubpacketData::KeyExpirationTime(d) => Some(*d),
792                _ => None,
793            })
794        })
795    }
796
797    pub fn signature_expiration_time(&self) -> Option<Duration> {
798        self.config().and_then(|h| {
799            h.hashed_subpackets().find_map(|p| match &p.data {
800                SubpacketData::SignatureExpirationTime(d) => Some(*d),
801                _ => None,
802            })
803        })
804    }
805
806    pub fn created(&self) -> Option<Timestamp> {
807        self.config().and_then(|c| c.created())
808    }
809
810    pub fn issuer_key_id(&self) -> Vec<&KeyId> {
811        self.config().map(|c| c.issuer_key_id()).unwrap_or_default()
812    }
813
814    pub fn issuer_fingerprint(&self) -> Vec<&Fingerprint> {
815        self.config()
816            .map(|c| c.issuer_fingerprint())
817            .unwrap_or_default()
818    }
819
820    pub fn preferred_symmetric_algs(&self) -> &[SymmetricKeyAlgorithm] {
821        self.config()
822            .and_then(|c| {
823                c.hashed_subpackets().find_map(|p| match &p.data {
824                    SubpacketData::PreferredSymmetricAlgorithms(d) => Some(&d[..]),
825                    _ => None,
826                })
827            })
828            .unwrap_or_else(|| &[][..])
829    }
830
831    pub fn preferred_aead_algs(&self) -> &[(SymmetricKeyAlgorithm, AeadAlgorithm)] {
832        self.config()
833            .and_then(|c| {
834                c.hashed_subpackets().find_map(|p| match &p.data {
835                    SubpacketData::PreferredAeadAlgorithms(d) => Some(&d[..]),
836                    _ => None,
837                })
838            })
839            .unwrap_or_else(|| &[][..])
840    }
841
842    pub fn preferred_hash_algs(&self) -> &[HashAlgorithm] {
843        self.config()
844            .and_then(|c| {
845                c.hashed_subpackets().find_map(|p| match &p.data {
846                    SubpacketData::PreferredHashAlgorithms(d) => Some(&d[..]),
847                    _ => None,
848                })
849            })
850            .unwrap_or_else(|| &[][..])
851    }
852
853    pub fn preferred_compression_algs(&self) -> &[CompressionAlgorithm] {
854        self.config()
855            .and_then(|c| {
856                c.hashed_subpackets().find_map(|p| match &p.data {
857                    SubpacketData::PreferredCompressionAlgorithms(d) => Some(&d[..]),
858                    _ => None,
859                })
860            })
861            .unwrap_or_else(|| &[][..])
862    }
863
864    pub fn key_server_prefs(&self) -> &[u8] {
865        self.config()
866            .and_then(|c| {
867                c.hashed_subpackets().find_map(|p| match &p.data {
868                    SubpacketData::KeyServerPreferences(d) => Some(&d[..]),
869                    _ => None,
870                })
871            })
872            .unwrap_or_else(|| &[][..])
873    }
874
875    pub fn key_flags(&self) -> KeyFlags {
876        self.config()
877            .and_then(|c| {
878                c.hashed_subpackets().find_map(|p| match &p.data {
879                    SubpacketData::KeyFlags(flags) => Some(flags.clone()),
880                    _ => None,
881                })
882            })
883            .unwrap_or_default()
884    }
885
886    pub fn features(&self) -> Option<&Features> {
887        self.config().and_then(|c| {
888            c.hashed_subpackets().find_map(|p| match &p.data {
889                SubpacketData::Features(feat) => Some(feat),
890                _ => None,
891            })
892        })
893    }
894
895    pub fn revocation_reason_code(&self) -> Option<&RevocationCode> {
896        self.config().and_then(|c| {
897            c.hashed_subpackets().find_map(|p| match &p.data {
898                SubpacketData::RevocationReason(code, _) => Some(code),
899                _ => None,
900            })
901        })
902    }
903
904    pub fn revocation_reason_string(&self) -> Option<&Bytes> {
905        self.config().and_then(|c| {
906            c.hashed_subpackets().find_map(|p| match &p.data {
907                SubpacketData::RevocationReason(_, reason) => Some(reason),
908                _ => None,
909            })
910        })
911    }
912
913    pub fn is_primary(&self) -> bool {
914        self.config()
915            .and_then(|c| {
916                c.hashed_subpackets().find_map(|p| match &p.data {
917                    SubpacketData::IsPrimary(d) => Some(*d),
918                    _ => None,
919                })
920            })
921            .unwrap_or(false)
922    }
923
924    pub fn is_revocable(&self) -> bool {
925        self.config()
926            .and_then(|c| {
927                c.hashed_subpackets().find_map(|p| match &p.data {
928                    SubpacketData::Revocable(d) => Some(*d),
929                    _ => None,
930                })
931            })
932            .unwrap_or(true)
933    }
934
935    pub fn embedded_signature(&self) -> Option<&Signature> {
936        // We consider data from both the hashed and unhashed area here, because the embedded
937        // signature is inherently cryptographically secured. An attacker can't add a valid
938        // embedded signature, canonicalization will remove any invalid embedded signature
939        // subpackets.
940        if let Some(sub) = self.config().and_then(|c| {
941            c.hashed_subpackets().find_map(|p| match &p.data {
942                SubpacketData::EmbeddedSignature(d) => Some(&**d),
943                _ => None,
944            })
945        }) {
946            return Some(sub);
947        }
948        if let Some(sub) = self.config().and_then(|c| {
949            c.unhashed_subpackets().find_map(|p| match &p.data {
950                SubpacketData::EmbeddedSignature(d) => Some(&**d),
951                _ => None,
952            })
953        }) {
954            return Some(sub);
955        }
956
957        None
958    }
959
960    pub fn preferred_key_server(&self) -> Option<&str> {
961        self.config().and_then(|c| {
962            c.hashed_subpackets().find_map(|p| match &p.data {
963                SubpacketData::PreferredKeyServer(d) => Some(d.as_str()),
964                _ => None,
965            })
966        })
967    }
968
969    pub fn notations(&self) -> Vec<&Notation> {
970        self.config()
971            .map(|c| {
972                c.hashed_subpackets()
973                    .filter_map(|p| match &p.data {
974                        SubpacketData::Notation(d) => Some(d),
975                        _ => None,
976                    })
977                    .collect::<Vec<_>>()
978            })
979            .unwrap_or_default()
980    }
981
982    pub fn revocation_key(&self) -> Option<&types::RevocationKey> {
983        self.config().and_then(|c| {
984            c.hashed_subpackets().find_map(|p| match &p.data {
985                SubpacketData::RevocationKey(d) => Some(d),
986                _ => None,
987            })
988        })
989    }
990
991    /// Gets the user id of the signer
992    ///
993    /// Note that the user id may not be valid utf-8, if it was created
994    /// using a different encoding. But since the RFC describes every
995    /// text as utf-8 it is up to the caller whether to error on non utf-8 data.
996    pub fn signers_userid(&self) -> Option<&Bytes> {
997        self.config().and_then(|c| {
998            c.hashed_subpackets().find_map(|p| match &p.data {
999                SubpacketData::SignersUserID(d) => Some(d),
1000                _ => None,
1001            })
1002        })
1003    }
1004
1005    pub fn policy_uri(&self) -> Option<&str> {
1006        self.config().and_then(|c| {
1007            c.hashed_subpackets().find_map(|p| match &p.data {
1008                SubpacketData::PolicyURI(d) => Some(d.as_ref()),
1009                _ => None,
1010            })
1011        })
1012    }
1013
1014    pub fn trust_signature(&self) -> Option<(u8, u8)> {
1015        self.config().and_then(|c| {
1016            c.hashed_subpackets().find_map(|p| match &p.data {
1017                SubpacketData::TrustSignature(depth, value) => Some((*depth, *value)),
1018                _ => None,
1019            })
1020        })
1021    }
1022
1023    pub fn regular_expression(&self) -> Option<&Bytes> {
1024        self.config().and_then(|c| {
1025            c.hashed_subpackets().find_map(|p| match &p.data {
1026                SubpacketData::RegularExpression(d) => Some(d),
1027                _ => None,
1028            })
1029        })
1030    }
1031
1032    pub fn exportable_certification(&self) -> bool {
1033        self.config()
1034            .and_then(|c| {
1035                c.hashed_subpackets().find_map(|p| match &p.data {
1036                    SubpacketData::ExportableCertification(d) => Some(*d),
1037                    _ => None,
1038                })
1039            })
1040            .unwrap_or(true)
1041    }
1042}
1043
1044/// The version of a [`Signature`] packet
1045#[derive(derive_more::Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, IntoPrimitive)]
1046#[repr(u8)]
1047pub enum SignatureVersion {
1048    /// Deprecated
1049    V2 = 2,
1050    V3 = 3,
1051    V4 = 4,
1052    V5 = 5,
1053    V6 = 6,
1054
1055    #[num_enum(catch_all)]
1056    Other(#[debug("0x{:x}", _0)] u8),
1057}
1058
1059#[allow(clippy::derivable_impls)]
1060impl Default for SignatureVersion {
1061    fn default() -> Self {
1062        Self::V4
1063    }
1064}
1065
1066/// A signature type defines the meaning of an OpenPGP [`Signature`].
1067///
1068/// The signature type is part of the [`SignatureConfig`] metadata.
1069///
1070/// OpenPGP signatures over data use either [`SignatureType::Binary`] or [`SignatureType::Text`].
1071///
1072/// Most other signature types are used to form certificates (aka OpenPGP public keys), e.g.
1073/// to associate subkeys with a primary key, bind identities to a certificate, and specify
1074/// various certificate metadata such as expiration/revocation status, and algorithm preferences.
1075///
1076/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-signature-types>
1077#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1078#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
1079#[repr(u8)]
1080pub enum SignatureType {
1081    /// Signature of a binary document.
1082    /// This means the signer owns it, created it, or certifies that it has not been modified.
1083    Binary = 0x00,
1084    /// Signature of a canonical text document.
1085    /// This means the signer owns it, created it, or certifies that it
1086    /// has not been modified.  The signature is calculated over the text
1087    /// data with its line endings converted to `<CR><LF>`.
1088    Text = 0x01,
1089    /// Standalone signature.
1090    /// This signature is a signature of only its own subpacket contents.
1091    /// It is calculated identically to a signature over a zero-length
1092    /// binary document.  Note that it doesn't make sense to have a V3 standalone signature.
1093    Standalone = 0x02,
1094    /// Generic certification of a User ID and Public-Key packet.
1095    /// The issuer of this certification does not make any particular
1096    /// assertion as to how well the certifier has checked that the owner
1097    /// of the key is in fact the person described by the User ID.
1098    CertGeneric = 0x10,
1099    /// Persona certification of a User ID and Public-Key packet.
1100    /// The issuer of this certification has not done any verification of
1101    /// the claim that the owner of this key is the User ID specified.
1102    CertPersona = 0x11,
1103    /// Casual certification of a User ID and Public-Key packet.
1104    /// The issuer of this certification has done some casual
1105    /// verification of the claim of identity.
1106    CertCasual = 0x12,
1107    /// Positive certification of a User ID and Public-Key packet.
1108    /// The issuer of this certification has done substantial
1109    /// verification of the claim of identity.
1110    ///
1111    /// Most OpenPGP implementations make their "key signatures" as 0x10
1112    /// certifications.  Some implementations can issue 0x11-0x13
1113    /// certifications, but few differentiate between the types.
1114    CertPositive = 0x13,
1115    /// Subkey Binding Signature
1116    /// This signature is a statement by the top-level signing key that
1117    /// indicates that it owns the subkey.  This signature is calculated
1118    /// directly on the primary key and subkey, and not on any User ID or
1119    /// other packets.  A signature that binds a signing subkey MUST have
1120    /// an Embedded Signature subpacket in this binding signature that
1121    /// contains a 0x19 signature made by the signing subkey on the
1122    /// primary key and subkey.
1123    SubkeyBinding = 0x18,
1124    /// Primary Key Binding Signature
1125    /// This signature is a statement by a signing subkey, indicating
1126    /// that it is owned by the primary key and subkey.  This signature
1127    /// is calculated the same way as a 0x18 signature: directly on the
1128    /// primary key and subkey, and not on any User ID or other packets.
1129    KeyBinding = 0x19,
1130    /// Signature directly on a key
1131    /// This signature is calculated directly on a key.  It binds the
1132    /// information in the Signature subpackets to the key, and is
1133    /// appropriate to be used for subpackets that provide information
1134    /// about the key, such as the Revocation Key subpacket.  It is also
1135    /// appropriate for statements that non-self certifiers want to make
1136    /// about the key itself, rather than the binding between a key and a name.
1137    Key = 0x1F,
1138    /// Key revocation signature
1139    /// The signature is calculated directly on the key being revoked.  A
1140    /// revoked key is not to be used.  Only revocation signatures by the
1141    /// key being revoked, or by an authorized revocation key, should be
1142    /// considered valid revocation signatures.
1143    KeyRevocation = 0x20,
1144    /// Subkey revocation signature
1145    /// The signature is calculated directly on the subkey being revoked.
1146    /// A revoked subkey is not to be used.  Only revocation signatures
1147    /// by the top-level signature key that is bound to this subkey, or
1148    /// by an authorized revocation key, should be considered valid
1149    /// revocation signatures.
1150    SubkeyRevocation = 0x28,
1151    /// Certification revocation signature
1152    /// This signature revokes an earlier User ID certification signature
1153    /// (signature class 0x10 through 0x13) or direct-key signature
1154    /// (0x1F).  It should be issued by the same key that issued the
1155    /// revoked signature or an authorized revocation key.  The signature
1156    /// is computed over the same data as the certificate that it
1157    /// revokes, and should have a later creation date than that
1158    /// certificate.
1159    CertRevocation = 0x30,
1160    /// Timestamp signature.
1161    /// This signature is only meaningful for the timestamp contained in
1162    /// it.
1163    Timestamp = 0x40,
1164    /// Third-Party Confirmation signature.
1165    /// This signature is a signature over some other OpenPGP Signature
1166    /// packet(s).  It is analogous to a notary seal on the signed data.
1167    /// A third-party signature SHOULD include Signature Target
1168    /// subpacket(s) to give easy identification.  Note that we really do
1169    /// mean SHOULD.  There are plausible uses for this (such as a blind
1170    /// party that only sees the signature, not the key or source
1171    /// document) that cannot include a target subpacket.
1172    ThirdParty = 0x50,
1173
1174    #[num_enum(catch_all)]
1175    Other(#[cfg_attr(test, proptest(strategy = "0x51u8.."))] u8),
1176}
1177
1178pub const CERTIFICATION_SIGNATURE_TYPES: &[SignatureType] = &[
1179    SignatureType::CertPositive,
1180    SignatureType::CertGeneric,
1181    SignatureType::CertCasual,
1182    SignatureType::CertPersona,
1183];
1184
1185/// Key Flags signature subpacket
1186///
1187/// A key flag is a semantical annotation to specify which OpenPGP operations a component key
1188/// is intended for.
1189///
1190/// Key flags usually consist of only 1 byte, but the specification allows extension of the field,
1191/// making it potentially arbitrarily long.
1192/// Fields that are currently reserved in the specification can make Key Flags up to 2 bytes long.
1193///
1194/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1195#[derive(Clone, PartialEq, Eq, Debug)]
1196pub struct KeyFlags {
1197    /// Handles the first two bytes.
1198    known: KnownKeyFlags,
1199    /// Any additional key flag bytes.
1200    rest: Option<Bytes>,
1201    /// Need to store this, to fully roundtrip..
1202    original_len: usize,
1203}
1204
1205impl Default for KeyFlags {
1206    fn default() -> Self {
1207        Self {
1208            known: KnownKeyFlags::default(),
1209            rest: None,
1210            original_len: 1,
1211        }
1212    }
1213}
1214
1215impl KeyFlags {
1216    /// Parse the key flags from the given buffer.
1217    pub fn try_from_reader<B: BufRead>(mut reader: B) -> Result<Self> {
1218        let mut buf = reader.rest()?.freeze();
1219        let remaining = buf.len();
1220
1221        if remaining == 0 {
1222            return Ok(Self {
1223                known: KnownKeyFlags::default(),
1224                rest: None,
1225                original_len: remaining,
1226            });
1227        }
1228        if remaining == 1 {
1229            let known = KnownKeyFlags::from_bits(buf.read_u8()? as u16);
1230            return Ok(Self {
1231                known,
1232                rest: None,
1233                original_len: remaining,
1234            });
1235        }
1236        if remaining == 2 {
1237            let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1238            return Ok(Self {
1239                known,
1240                rest: None,
1241                original_len: remaining,
1242            });
1243        }
1244        let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1245        let rest = Some(buf.rest());
1246        Ok(Self {
1247            known,
1248            rest,
1249            original_len: remaining,
1250        })
1251    }
1252
1253    pub fn set_certify(&mut self, val: bool) {
1254        self.known.set_certify(val);
1255    }
1256    pub fn set_encrypt_comms(&mut self, val: bool) {
1257        self.known.set_encrypt_comms(val);
1258    }
1259    pub fn set_encrypt_storage(&mut self, val: bool) {
1260        self.known.set_encrypt_storage(val);
1261    }
1262    pub fn set_sign(&mut self, val: bool) {
1263        self.known.set_sign(val);
1264    }
1265    pub fn set_shared(&mut self, val: bool) {
1266        self.known.set_shared(val);
1267    }
1268    pub fn set_authentication(&mut self, val: bool) {
1269        self.known.set_authentication(val);
1270    }
1271    pub fn set_group(&mut self, val: bool) {
1272        self.known.set_group(val);
1273    }
1274
1275    pub fn set_adsk(&mut self, val: bool) {
1276        self.known.set_adsk(val);
1277    }
1278
1279    pub fn set_timestamping(&mut self, val: bool) {
1280        self.known.set_timestamping(val);
1281    }
1282
1283    pub fn certify(&self) -> bool {
1284        self.known.certify()
1285    }
1286
1287    pub fn encrypt_comms(&self) -> bool {
1288        self.known.encrypt_comms()
1289    }
1290
1291    pub fn encrypt_storage(&self) -> bool {
1292        self.known.encrypt_storage()
1293    }
1294
1295    pub fn sign(&self) -> bool {
1296        self.known.sign()
1297    }
1298
1299    pub fn shared(&self) -> bool {
1300        self.known.shared()
1301    }
1302
1303    pub fn authentication(&self) -> bool {
1304        self.known.authentication()
1305    }
1306
1307    /// Draft key flag: "This key may be used for forwarded communication"
1308    ///
1309    /// Ref <https://datatracker.ietf.org/doc/html/draft-wussler-openpgp-forwarding#name-key-flag-0x40>
1310    pub fn draft_decrypt_forwarded(&self) -> bool {
1311        self.known.draft_decrypt_forwarded()
1312    }
1313
1314    pub fn group(&self) -> bool {
1315        self.known.group()
1316    }
1317
1318    pub fn adsk(&self) -> bool {
1319        self.known.adsk()
1320    }
1321
1322    pub fn timestamping(&self) -> bool {
1323        self.known.timestamping()
1324    }
1325}
1326
1327impl Serialize for KeyFlags {
1328    fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1329        if self.original_len == 0 {
1330            return Ok(());
1331        }
1332
1333        let [a, b] = self.known.into_bits().to_le_bytes();
1334        writer.write_u8(a)?;
1335
1336        if self.original_len > 1 || b != 0 {
1337            writer.write_u8(b)?;
1338        }
1339
1340        if let Some(ref rest) = self.rest {
1341            writer.write_all(rest)?;
1342        }
1343        Ok(())
1344    }
1345
1346    fn write_len(&self) -> usize {
1347        if self.original_len == 0 {
1348            return 0;
1349        }
1350        let mut sum = 0;
1351        let [_, b] = self.known.into_bits().to_le_bytes();
1352        if self.original_len > 1 || b > 0 {
1353            sum += 2;
1354        } else {
1355            sum += 1;
1356        }
1357
1358        if let Some(ref rest) = self.rest {
1359            sum += rest.len();
1360        }
1361        sum
1362    }
1363}
1364
1365/// Encodes the known fields of a [`KeyFlags`].
1366///
1367/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1368#[bitfield(u16, order = lsb)]
1369#[derive(PartialEq, Eq, Copy, Clone)]
1370pub struct KnownKeyFlags {
1371    #[bits(1)]
1372    certify: bool,
1373    #[bits(1)]
1374    sign: bool,
1375    #[bits(1)]
1376    encrypt_comms: bool,
1377    #[bits(1)]
1378    encrypt_storage: bool,
1379    #[bits(1)]
1380    shared: bool,
1381    #[bits(1)]
1382    authentication: bool,
1383    #[bits(1)]
1384    draft_decrypt_forwarded: bool,
1385    #[bits(1)]
1386    group: bool,
1387    #[bits(2)]
1388    _padding1: u8,
1389    #[bits(1)]
1390    adsk: bool,
1391    #[bits(1)]
1392    timestamping: bool,
1393    #[bits(4)]
1394    _padding2: u8,
1395}
1396
1397/// Features signature subpacket.
1398///
1399/// The Features subpacket denotes which advanced OpenPGP features a user's implementation
1400/// supports, mainly as a signal to communication peers.
1401///
1402/// Features are encoded as "N octets of flags", but currently typically use 1 byte.
1403/// (Only the first 4 bits have been specified so far)
1404///
1405/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-features>
1406#[derive(Clone, PartialEq, Eq, Debug)]
1407pub struct Features {
1408    /// Handles the first byte.
1409    /// Can be None to encode Features subpackets that are 0 byte long.
1410    first: Option<KnownFeatures>,
1411
1412    /// Any additional features bytes.
1413    /// (Must be empty if "known" is None.)
1414    rest: Vec<u8>,
1415}
1416
1417impl Default for Features {
1418    fn default() -> Self {
1419        Self {
1420            first: Some(KnownFeatures::default()),
1421            rest: vec![],
1422        }
1423    }
1424}
1425
1426impl From<&[u8]> for Features {
1427    fn from(value: &[u8]) -> Self {
1428        match value.len() {
1429            0 => Self {
1430                first: None,
1431                rest: vec![],
1432            },
1433            _ => Self {
1434                first: Some(KnownFeatures(value[0])),
1435                rest: value[1..].to_vec(),
1436            },
1437        }
1438    }
1439}
1440
1441impl From<&Features> for Vec<u8> {
1442    fn from(value: &Features) -> Self {
1443        let mut v = vec![];
1444        value.to_writer(&mut v).expect("vec");
1445        v
1446    }
1447}
1448
1449impl From<KnownFeatures> for Features {
1450    fn from(value: KnownFeatures) -> Self {
1451        Self {
1452            first: Some(value),
1453            rest: vec![],
1454        }
1455    }
1456}
1457
1458impl Features {
1459    pub fn new() -> Self {
1460        Self::default()
1461    }
1462
1463    pub fn seipd_v1(&self) -> bool {
1464        match self.first {
1465            Some(k) => k.seipd_v1(),
1466            None => false,
1467        }
1468    }
1469
1470    pub fn set_seipd_v1(&mut self, val: bool) {
1471        if self.first.is_none() {
1472            self.first = Some(KnownFeatures::default());
1473        }
1474
1475        // Should always be Some!
1476        if let Some(k) = self.first.as_mut() {
1477            k.set_seipd_v1(val);
1478        }
1479    }
1480
1481    pub fn seipd_v2(&self) -> bool {
1482        match self.first {
1483            Some(k) => k.seipd_v2(),
1484            None => false,
1485        }
1486    }
1487
1488    pub fn set_seipd_v2(&mut self, val: bool) {
1489        if self.first.is_none() {
1490            self.first = Some(KnownFeatures::default());
1491        }
1492
1493        // Should always be Some!
1494        if let Some(k) = self.first.as_mut() {
1495            k.set_seipd_v2(val);
1496        }
1497    }
1498}
1499
1500impl Serialize for Features {
1501    fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1502        if let Some(k) = self.first {
1503            writer.write_u8(k.0)?;
1504            writer.write_all(&self.rest)?;
1505        }
1506
1507        Ok(())
1508    }
1509
1510    fn write_len(&self) -> usize {
1511        if self.first.is_none() {
1512            0
1513        } else {
1514            1 + self.rest.len()
1515        }
1516    }
1517}
1518
1519/// Encodes the first byte of a [`Features`].
1520///
1521/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-features>
1522#[bitfield(u8)]
1523#[derive(PartialEq, Eq, Copy, Clone)]
1524pub struct KnownFeatures {
1525    /// Support for "Version 1 Symmetrically Encrypted and Integrity Protected Data packet"
1526    #[bits(1)]
1527    seipd_v1: bool,
1528
1529    /// Not standardized in OpenPGP, but used in the LibrePGP fork.
1530    /// Signals support for GnuPG-specific "OCB" encryption packet format.
1531    #[bits(1)]
1532    _libre_ocb: u8,
1533
1534    /// Not standardized in OpenPGP, but used in the LibrePGP fork.
1535    /// Semantics unclear.
1536    #[bits(1)]
1537    _libre_v5_keys: u8,
1538
1539    /// Support for "Version 2 Symmetrically Encrypted and Integrity Protected Data packet"
1540    #[bits(1)]
1541    seipd_v2: bool,
1542
1543    #[bits(4)]
1544    _padding: u8,
1545}
1546
1547/// Notation Data signature subpacket
1548///
1549/// Used as the payload of a [`SubpacketData::Notation`].
1550///
1551/// This subpacket describes a "notation" on the signature that the issuer wishes to make.
1552/// The notation has a name and a value, each of which are strings of octets.
1553/// There may be more than one notation in a signature.
1554/// Notations can be used for any extension the issuer of the signature cares to make.
1555///
1556/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-notation-data>
1557#[derive(Debug, PartialEq, Eq, Clone)]
1558pub struct Notation {
1559    pub readable: bool,
1560    pub name: Bytes,
1561    pub value: Bytes,
1562}
1563
1564/// Value of a [`SubpacketData::RevocationReason`] signature subpacket
1565///
1566/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-reason-for-revocation>
1567#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1568#[repr(u8)]
1569pub enum RevocationCode {
1570    /// No reason specified (key revocations or cert revocations)
1571    NoReason = 0,
1572    /// Key is superseded (key revocations)
1573    KeySuperseded = 1,
1574    /// Key material has been compromised (key revocations)
1575    KeyCompromised = 2,
1576    /// Key is retired and no longer used (key revocations)
1577    KeyRetired = 3,
1578    /// User ID information is no longer valid (cert revocations)
1579    CertUserIdInvalid = 32,
1580
1581    /// Private Use range (from OpenPGP)
1582    Private100 = 100,
1583    Private101 = 101,
1584    Private102 = 102,
1585    Private103 = 103,
1586    Private104 = 104,
1587    Private105 = 105,
1588    Private106 = 106,
1589    Private107 = 107,
1590    Private108 = 108,
1591    Private109 = 109,
1592    Private110 = 110,
1593
1594    /// Undefined code
1595    #[num_enum(catch_all)]
1596    Other(u8),
1597}
1598
1599impl PacketTrait for Signature {
1600    fn packet_header(&self) -> &PacketHeader {
1601        &self.packet_header
1602    }
1603}
1604
1605pub(super) fn serialize_for_hashing<K: KeyDetails + Serialize>(
1606    key: &K,
1607    hasher: &mut Box<dyn DynDigest + Send>,
1608) -> Result<()> {
1609    let key_len = key.write_len();
1610
1611    let mut writer = WriteHasher(hasher);
1612
1613    // old style packet header for the key
1614    match key.version() {
1615        KeyVersion::V2 | KeyVersion::V3 | KeyVersion::V4 => {
1616            // When a v4 signature is made over a key, the hash data starts with the octet 0x99,
1617            // followed by a two-octet length of the key, and then the body of the key packet.
1618            writer.write_u8(0x99)?;
1619            writer.write_u16::<BigEndian>(key_len.try_into()?)?;
1620        }
1621
1622        KeyVersion::V6 => {
1623            // When a v6 signature is made over a key, the hash data starts with the salt
1624            // [NOTE: the salt is hashed in packet/signature/config.rs],
1625
1626            // then octet 0x9B, followed by a four-octet length of the key,
1627            // and then the body of the key packet.
1628            writer.write_u8(0x9b)?;
1629            writer.write_u32::<BigEndian>(key_len.try_into()?)?;
1630        }
1631
1632        v => unimplemented_err!("key version {:?}", v),
1633    }
1634
1635    key.to_writer(&mut writer)?;
1636
1637    Ok(())
1638}
1639
1640#[cfg(test)]
1641mod tests {
1642    use std::io::Cursor;
1643
1644    use bytes::BytesMut;
1645
1646    use super::*;
1647    use crate::packet::SubpacketType;
1648
1649    /// keyflags being all zeros..are special
1650    #[test]
1651    fn test_keyflags_crazy_versions() {
1652        for i in 0..1024 {
1653            println!("size {i}");
1654            // I write this with pain...
1655            let source = BytesMut::zeroed(i).freeze();
1656            let flags = KeyFlags::try_from_reader(&source[..]).unwrap();
1657            assert_eq!(&flags.to_bytes().unwrap(), &source);
1658        }
1659    }
1660
1661    #[test]
1662    fn test_keyflags_1_byte() {
1663        let flags: KeyFlags = Default::default();
1664        assert_eq!(flags.to_bytes().unwrap(), vec![0x00]);
1665
1666        let mut flags = KeyFlags::default();
1667        flags.set_certify(true);
1668        assert!(flags.certify());
1669        assert_eq!(flags.to_bytes().unwrap(), vec![0x01]);
1670
1671        let mut flags = KeyFlags::default();
1672        flags.set_sign(true);
1673        assert_eq!(flags.to_bytes().unwrap(), vec![0x02]);
1674
1675        let mut flags = KeyFlags::default();
1676        flags.set_encrypt_comms(true);
1677        assert_eq!(flags.to_bytes().unwrap(), vec![0x04]);
1678
1679        let mut flags = KeyFlags::default();
1680        flags.set_encrypt_storage(true);
1681        assert_eq!(flags.to_bytes().unwrap(), vec![0x08]);
1682
1683        let mut flags = KeyFlags::default();
1684        flags.set_shared(true);
1685        assert_eq!(flags.to_bytes().unwrap(), vec![0x10]);
1686
1687        let mut flags = KeyFlags::default();
1688        flags.set_authentication(true);
1689        assert_eq!(flags.to_bytes().unwrap(), vec![0x20]);
1690
1691        let mut flags = KeyFlags::default();
1692        flags.set_group(true);
1693        assert_eq!(flags.to_bytes().unwrap(), vec![0x80]);
1694
1695        let mut flags = KeyFlags::default();
1696        flags.set_certify(true);
1697        flags.set_sign(true);
1698        assert_eq!(flags.to_bytes().unwrap(), vec![0x03]);
1699    }
1700
1701    #[test]
1702    fn test_keyflags_2_bytes() {
1703        let mut flags: KeyFlags = Default::default();
1704        flags.set_adsk(true);
1705        assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x04]);
1706
1707        let mut flags: KeyFlags = Default::default();
1708        flags.set_timestamping(true);
1709        assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x08]);
1710
1711        let mut flags: KeyFlags = Default::default();
1712        flags.set_timestamping(true);
1713        flags.set_certify(true);
1714        flags.set_sign(true);
1715
1716        assert_eq!(flags.to_bytes().unwrap(), vec![0x03, 0x08]);
1717    }
1718
1719    #[test]
1720    fn test_features() {
1721        use crate::packet::Features;
1722
1723        // deserialize/serialize, getters
1724        {
1725            let empty: Features = (&[][..]).into();
1726            assert_eq!(empty.seipd_v1(), false);
1727            assert_eq!(empty.seipd_v2(), false);
1728
1729            assert_eq!(empty.write_len(), 0);
1730            let mut out = vec![];
1731            empty.to_writer(&mut out).expect("write");
1732            assert!(out.is_empty());
1733        }
1734        {
1735            let seipdv1: Features = (&[0x01][..]).into();
1736            assert_eq!(seipdv1.seipd_v1(), true);
1737            assert_eq!(seipdv1.seipd_v2(), false);
1738
1739            assert_eq!(seipdv1.write_len(), 1);
1740            let mut out = vec![];
1741            seipdv1.to_writer(&mut out).expect("write");
1742            assert_eq!(out, vec![0x01]);
1743        }
1744        {
1745            let allbits: Features = (&[0xff][..]).into();
1746            assert_eq!(allbits.seipd_v1(), true);
1747            assert_eq!(allbits.seipd_v2(), true);
1748
1749            assert_eq!(allbits.write_len(), 1);
1750            let mut out = vec![];
1751            allbits.to_writer(&mut out).expect("write");
1752            assert_eq!(out, vec![0xff]);
1753        }
1754        {
1755            let three_bytes: Features = (&[0x09, 0xaa, 0xbb][..]).into();
1756            assert_eq!(three_bytes.seipd_v1(), true);
1757            assert_eq!(three_bytes.seipd_v2(), true);
1758
1759            assert_eq!(three_bytes.write_len(), 3);
1760            let mut out = vec![];
1761            three_bytes.to_writer(&mut out).expect("write");
1762            assert_eq!(out, vec![0x09, 0xaa, 0xbb]);
1763        }
1764
1765        // setters
1766        {
1767            let mut empty: Features = (&[][..]).into();
1768            assert!(Vec::<u8>::from(&empty).is_empty());
1769
1770            empty.set_seipd_v1(true);
1771            assert_eq!(Vec::<u8>::from(&empty), vec![0x01]);
1772        }
1773        {
1774            let mut default = Features::default();
1775            assert_eq!(Vec::<u8>::from(&default), vec![0x00]);
1776
1777            default.set_seipd_v1(true);
1778            assert_eq!(Vec::<u8>::from(&default), vec![0x01]);
1779
1780            default.set_seipd_v2(true);
1781            assert_eq!(Vec::<u8>::from(&default), vec![0x09]);
1782        }
1783        {
1784            let mut allbits: Features = (&[0xff][..]).into();
1785
1786            allbits.set_seipd_v1(false);
1787            assert_eq!(Vec::<u8>::from(&allbits), vec![0xfe]);
1788
1789            allbits.set_seipd_v2(false);
1790            assert_eq!(Vec::<u8>::from(&allbits), vec![0xf6]);
1791        }
1792        {
1793            let mut three_bytes: Features = (&[0x00, 0xaa, 0xbb][..]).into();
1794            three_bytes.set_seipd_v2(true);
1795            assert_eq!(Vec::<u8>::from(&three_bytes), vec![0x08, 0xaa, 0xbb]);
1796        }
1797    }
1798
1799    #[test]
1800    fn test_critical() {
1801        use SubpacketType::*;
1802        let cases = [
1803            SignatureCreationTime,
1804            SignatureExpirationTime,
1805            ExportableCertification,
1806            TrustSignature,
1807            RegularExpression,
1808            Revocable,
1809            KeyExpirationTime,
1810            PreferredSymmetricAlgorithms,
1811            RevocationKey,
1812            IssuerKeyId,
1813            Notation,
1814            PreferredHashAlgorithms,
1815            PreferredCompressionAlgorithms,
1816            KeyServerPreferences,
1817            PreferredKeyServer,
1818            PrimaryUserId,
1819            PolicyURI,
1820            KeyFlags,
1821            SignersUserID,
1822            RevocationReason,
1823            Features,
1824            SignatureTarget,
1825            EmbeddedSignature,
1826            IssuerFingerprint,
1827            PreferredAead,
1828            Experimental(101),
1829            Other(95),
1830        ];
1831        for case in cases {
1832            assert_eq!(SubpacketType::from_u8(case.as_u8(false)), (case, false));
1833            assert_eq!(SubpacketType::from_u8(case.as_u8(true)), (case, true));
1834        }
1835    }
1836
1837    use proptest::prelude::*;
1838
1839    use crate::composed::DetachedSignature;
1840
1841    impl Arbitrary for KeyFlags {
1842        type Parameters = ();
1843        type Strategy = BoxedStrategy<Self>;
1844
1845        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
1846            proptest::collection::vec(0u8..255, 1..500)
1847                .prop_map(|v| KeyFlags::try_from_reader(&mut &v[..]).unwrap())
1848                .boxed()
1849        }
1850    }
1851
1852    #[test]
1853    fn unhashed_area_modification() {
1854        fn subpacket_type_list(sig: &Signature) -> Vec<SubpacketType> {
1855            sig.config()
1856                .unwrap()
1857                .unhashed_subpackets
1858                .iter()
1859                .map(Subpacket::typ)
1860                .collect()
1861        }
1862
1863        use crate::composed::Deserializable;
1864
1865        let mut sig = DetachedSignature::from_armor_single(Cursor::new(
1866            "-----BEGIN PGP SIGNATURE-----
1867
1868wpoEEBYIAEIFAmheZZEWIQT8Y2QNsPXIvVyHlK1LkdWvyoDDywIbAwIeAQQLCQgH
1869BhUOCgkMCAEWDScJAggCBwIJAQgBBwECGQEACgkQS5HVr8qAw8swhAD/RFBBueDN
1870ClWUWHgCj+FmHElqrUO4YVePdt2KRkniPJ4A/jtOCzD7vZJZs0yP4xQ78PEsUST0
1871pwsJtT3sJB2q5NoA
1872=XphF
1873-----END PGP SIGNATURE-----",
1874        ))
1875        .unwrap()
1876        .0
1877        .signature;
1878
1879        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(154));
1880
1881        sig.unhashed_subpacket_push(
1882            Subpacket::regular(SubpacketData::Notation(Notation {
1883                readable: true,
1884                name: "foo".into(),
1885                value: "bar".into(),
1886            }))
1887            .unwrap(),
1888        )
1889        .unwrap();
1890        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(170));
1891        assert_eq!(
1892            &subpacket_type_list(&sig),
1893            &[SubpacketType::IssuerKeyId, SubpacketType::Notation]
1894        );
1895
1896        sig.unhashed_subpacket_insert(
1897            0,
1898            Subpacket::regular(SubpacketData::Notation(Notation {
1899                readable: true,
1900                name: "hello".into(),
1901                value: "world".into(),
1902            }))
1903            .unwrap(),
1904        )
1905        .unwrap();
1906        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
1907        assert_eq!(
1908            &subpacket_type_list(&sig),
1909            &[
1910                SubpacketType::Notation,
1911                SubpacketType::IssuerKeyId,
1912                SubpacketType::Notation
1913            ]
1914        );
1915
1916        sig.unhashed_subpackets_sort_by(|a, b| {
1917            a.typ()
1918                .as_u8(a.is_critical)
1919                .cmp(&b.typ().as_u8(b.is_critical))
1920        });
1921        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
1922        assert_eq!(
1923            &subpacket_type_list(&sig),
1924            &[
1925                SubpacketType::IssuerKeyId,
1926                SubpacketType::Notation,
1927                SubpacketType::Notation
1928            ]
1929        );
1930
1931        sig.unhashed_subpacket_remove(0).unwrap();
1932        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(180));
1933        assert_eq!(
1934            &subpacket_type_list(&sig),
1935            &[SubpacketType::Notation, SubpacketType::Notation]
1936        );
1937    }
1938
1939    proptest! {
1940        #[test]
1941        fn keyflags_write_len(flags: KeyFlags) {
1942            let mut buf = Vec::new();
1943            flags.to_writer(&mut buf).unwrap();
1944            prop_assert_eq!(buf.len(), flags.write_len());
1945        }
1946
1947        #[test]
1948        fn keyflags_packet_roundtrip(flags: KeyFlags) {
1949            let mut buf = Vec::new();
1950            flags.to_writer(&mut buf).unwrap();
1951            let new_flags = KeyFlags::try_from_reader(&mut &buf[..]).unwrap();
1952            prop_assert_eq!(flags, new_flags);
1953        }
1954    }
1955}