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 or certification revocation signature (for self-signatures).
531    ///
532    /// Allowed signature types are:
533    /// - Generic Certification Signature (Type ID 0x10)
534    /// - Persona Certification Signature (Type ID 0x11)
535    /// - Casual Certification Signature (Type ID 0x12)
536    /// - Positive Certification Signature (Type ID 0x13)
537    /// - Certification Revocation Signature (Type ID 0x30)
538    pub fn verify_certification<V>(&self, key: &V, tag: Tag, id: &impl Serialize) -> Result<()>
539    where
540        V: VerifyingKey + Serialize,
541    {
542        self.verify_third_party_certification(&key, &key, tag, id)
543    }
544
545    /// Verifies a (possibly third-party) certification signature or certification revocation signature.
546    ///
547    /// Allowed signature types are:
548    /// - Generic Certification Signature (Type ID 0x10)
549    /// - Persona Certification Signature (Type ID 0x11)
550    /// - Casual Certification Signature (Type ID 0x12)
551    /// - Positive Certification Signature (Type ID 0x13)
552    /// - Certification Revocation Signature (Type ID 0x30)
553    pub fn verify_third_party_certification<V, K>(
554        &self,
555        signee: &K,
556        signer: &V,
557        tag: Tag,
558        id: &impl Serialize,
559    ) -> Result<()>
560    where
561        V: VerifyingKey + Serialize,
562        K: KeyDetails + Serialize,
563    {
564        let InnerSignature::Known {
565            ref config,
566            ref signed_hash_value,
567            ref signature,
568        } = self.inner
569        else {
570            unsupported_err!("signature version {:?}", self.version());
571        };
572        let key_id = signee.legacy_key_id();
573        debug!("verifying certification {key_id:?} {self:#?}");
574
575        ensure!(
576            matches!(
577                config.typ,
578                SignatureType::CertGeneric
579                    | SignatureType::CertPersona
580                    | SignatureType::CertCasual
581                    | SignatureType::CertPositive
582                    | SignatureType::CertRevocation
583            ),
584            "Expected certification signature or certificate revocation signature"
585        );
586
587        Self::check_signature_key_version_alignment(&signer, config)?;
588        Self::check_signature_hash_strength(config)?;
589
590        ensure!(
591            Self::match_identity(self, signer),
592            "verify_certification: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
593            key_id,
594        );
595
596        let mut hasher = config.hash_alg.new_hasher()?;
597
598        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
599            hasher.update(salt.as_ref())
600        }
601
602        // the key of the signee
603        {
604            // TODO: this is different for V5
605            serialize_for_hashing(signee, &mut hasher)?;
606        }
607
608        // the packet content
609        {
610            let packet_len = id.write_len();
611
612            match config.version() {
613                SignatureVersion::V2 | SignatureVersion::V3 => {
614                    // Nothing to do
615                }
616                SignatureVersion::V4 | SignatureVersion::V6 => {
617                    let prefix = match tag {
618                        Tag::UserId => 0xB4,
619                        Tag::UserAttribute => 0xD1,
620                        _ => bail!("invalid tag for certification validation: {:?}", tag),
621                    };
622
623                    let mut prefix_buf = [prefix, 0u8, 0u8, 0u8, 0u8];
624                    BigEndian::write_u32(&mut prefix_buf[1..], packet_len.try_into()?);
625
626                    // prefixes
627                    hasher.update(&prefix_buf);
628                }
629                SignatureVersion::V5 => {
630                    bail!("v5 signature unsupported tpc")
631                }
632                SignatureVersion::Other(version) => {
633                    bail!("unsupported signature version: {:?}", version)
634                }
635            }
636
637            id.to_writer(&mut WriteHasher(&mut hasher))?;
638        }
639
640        let len = config.hash_signature_data(&mut hasher)?;
641        hasher.update(&config.trailer(len)?);
642
643        let hash = &hasher.finalize()[..];
644        ensure_eq!(
645            signed_hash_value,
646            &hash[0..2],
647            "certification: invalid signed hash value"
648        );
649
650        signer.verify(config.hash_alg, hash, signature)
651    }
652
653    /// Verifies a subkey binding (which binds a subkey to the primary key) or subkey revocation signature.
654    ///
655    /// The primary key is expected as `signer`, the subkey as `signee`.
656    ///
657    /// Allowed signature types are:
658    /// - Subkey Binding Signature (type ID 0x18)
659    /// - Subkey Revocation Signature (Type ID 0x28)
660    pub fn verify_subkey_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
661    where
662        V: VerifyingKey + Serialize,
663        K: KeyDetails + Serialize,
664    {
665        debug!("verifying subkey binding: {self:#?} - {signer:#?} - {signee:#?}",);
666
667        let InnerSignature::Known {
668            ref config,
669            ref signed_hash_value,
670            ref signature,
671        } = self.inner
672        else {
673            unsupported_err!("signature version {:?}", self.version());
674        };
675
676        ensure!(
677            matches!(
678                config.typ,
679                SignatureType::SubkeyBinding | SignatureType::SubkeyRevocation
680            ),
681            "Expected subkey binding or revocation signature"
682        );
683
684        Self::check_signature_key_version_alignment(&signer, config)?;
685        Self::check_signature_hash_strength(config)?;
686
687        let mut hasher = config.hash_alg.new_hasher()?;
688
689        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
690            hasher.update(salt.as_ref())
691        }
692
693        serialize_for_hashing(signer, &mut hasher)?; // primary
694        serialize_for_hashing(signee, &mut hasher)?; // subkey
695
696        let len = config.hash_signature_data(&mut hasher)?;
697        hasher.update(&config.trailer(len)?);
698
699        let hash = &hasher.finalize()[..];
700        ensure_eq!(
701            signed_hash_value,
702            &hash[0..2],
703            "subkey binding: invalid signed hash value"
704        );
705
706        signer.verify(config.hash_alg, hash, signature)
707    }
708
709    /// Verifies a primary key binding signature, or "back signature" (which links the primary to a signing subkey).
710    ///
711    /// The subkey is expected as `signer`, the primary key as `signee`.
712    ///
713    /// Allowed signature types are:
714    /// - Primary Key Binding Signature (type ID 0x19)
715    pub fn verify_primary_key_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
716    where
717        V: VerifyingKey + Serialize,
718        K: KeyDetails + Serialize,
719    {
720        debug!("verifying primary key binding: {self:#?} - {signer:#?} - {signee:#?}");
721
722        let InnerSignature::Known {
723            ref config,
724            ref signed_hash_value,
725            ref signature,
726        } = self.inner
727        else {
728            unsupported_err!("signature version {:?}", self.version());
729        };
730
731        ensure_eq!(
732            config.typ,
733            SignatureType::KeyBinding,
734            "Expected primary key binding signature"
735        );
736
737        Self::check_signature_key_version_alignment(&signer, config)?;
738        Self::check_signature_hash_strength(config)?;
739
740        let mut hasher = config.hash_alg.new_hasher()?;
741
742        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
743            hasher.update(salt.as_ref())
744        }
745
746        serialize_for_hashing(signee, &mut hasher)?; // primary
747        serialize_for_hashing(signer, &mut hasher)?; // subkey
748
749        let len = config.hash_signature_data(&mut hasher)?;
750        hasher.update(&config.trailer(len)?);
751
752        let hash = &hasher.finalize()[..];
753        ensure_eq!(
754            signed_hash_value,
755            &hash[0..2],
756            "key binding: invalid signed hash value"
757        );
758
759        signer.verify(config.hash_alg, hash, signature)
760    }
761
762    /// Verifies a direct key signature or a revocation.
763    pub fn verify_key<V>(&self, key: &V) -> Result<()>
764    where
765        V: VerifyingKey + Serialize,
766    {
767        self.verify_key_third_party(key, key)
768    }
769
770    /// Verifies a (possibly third-party) direct key signature or a revocation.
771    ///
772    /// Allowed signature types are:
773    /// - Direct Key Signature (Type ID 0x1F)
774    /// - Key Revocation Signature (Type ID 0x20)
775    pub fn verify_key_third_party<V, K>(&self, signee: &K, signer: &V) -> Result<()>
776    where
777        V: VerifyingKey + Serialize,
778        K: KeyDetails + Serialize,
779    {
780        debug!("verifying direct signature: {self:#?} - signer {signer:#?}, signee {signee:#?}");
781
782        let InnerSignature::Known {
783            ref config,
784            ref signed_hash_value,
785            ref signature,
786        } = self.inner
787        else {
788            unsupported_err!("signature version {:?}", self.version());
789        };
790        ensure!(
791            matches!(
792                config.typ,
793                SignatureType::Key | SignatureType::KeyRevocation
794            ),
795            "Expected direct key signature or key revocation signature"
796        );
797
798        Self::check_signature_key_version_alignment(&signer, config)?;
799        Self::check_signature_hash_strength(config)?;
800
801        ensure!(
802            Self::match_identity(self, signer),
803            "verify_key: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
804            &signer.legacy_key_id(),
805        );
806
807        let mut hasher = config.hash_alg.new_hasher()?;
808
809        if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
810            hasher.update(salt.as_ref())
811        }
812
813        serialize_for_hashing(signee, &mut hasher)?;
814
815        let len = config.hash_signature_data(&mut hasher)?;
816        hasher.update(&config.trailer(len)?);
817
818        let hash = &hasher.finalize()[..];
819        ensure_eq!(
820            signed_hash_value,
821            &hash[0..2],
822            "key: invalid signed hash value"
823        );
824
825        signer.verify(config.hash_alg, hash, signature)
826    }
827
828    /// Returns if the signature is a certification or not.
829    pub fn is_certification(&self) -> bool {
830        self.config()
831            .map(|c| c.is_certification())
832            .unwrap_or_default()
833    }
834
835    /// If the hashed area contains any KeyExpirationTime subpacket, then this
836    /// returns `Some(Duration)` of the first KeyExpirationTime subpacket encountered.
837    ///
838    /// If the hashed area contains no KeyExpirationTime subpacket, this returns `None`.
839    ///
840    /// (Note that a return value of `Some(Duration(0))` also means that no key expiration time
841    /// applies to the target component. This corresponds to a different wire-format
842    /// representation, but is semantically equivalent to `None`.)
843    pub fn key_expiration_time(&self) -> Option<Duration> {
844        self.config().and_then(|h| {
845            h.hashed_subpackets().find_map(|p| match &p.data {
846                SubpacketData::KeyExpirationTime(d) => Some(*d),
847                _ => None,
848            })
849        })
850    }
851
852    pub fn signature_expiration_time(&self) -> Option<Duration> {
853        self.config().and_then(|h| {
854            h.hashed_subpackets().find_map(|p| match &p.data {
855                SubpacketData::SignatureExpirationTime(d) => Some(*d),
856                _ => None,
857            })
858        })
859    }
860
861    pub fn created(&self) -> Option<Timestamp> {
862        self.config().and_then(|c| c.created())
863    }
864
865    pub fn issuer_key_id(&self) -> Vec<&KeyId> {
866        self.config().map(|c| c.issuer_key_id()).unwrap_or_default()
867    }
868
869    pub fn issuer_fingerprint(&self) -> Vec<&Fingerprint> {
870        self.config()
871            .map(|c| c.issuer_fingerprint())
872            .unwrap_or_default()
873    }
874
875    pub fn preferred_symmetric_algs(&self) -> &[SymmetricKeyAlgorithm] {
876        self.config()
877            .and_then(|c| {
878                c.hashed_subpackets().find_map(|p| match &p.data {
879                    SubpacketData::PreferredSymmetricAlgorithms(d) => Some(&d[..]),
880                    _ => None,
881                })
882            })
883            .unwrap_or_else(|| &[][..])
884    }
885
886    pub fn preferred_aead_algs(&self) -> &[(SymmetricKeyAlgorithm, AeadAlgorithm)] {
887        self.config()
888            .and_then(|c| {
889                c.hashed_subpackets().find_map(|p| match &p.data {
890                    SubpacketData::PreferredAeadAlgorithms(d) => Some(&d[..]),
891                    _ => None,
892                })
893            })
894            .unwrap_or_else(|| &[][..])
895    }
896
897    pub fn preferred_hash_algs(&self) -> &[HashAlgorithm] {
898        self.config()
899            .and_then(|c| {
900                c.hashed_subpackets().find_map(|p| match &p.data {
901                    SubpacketData::PreferredHashAlgorithms(d) => Some(&d[..]),
902                    _ => None,
903                })
904            })
905            .unwrap_or_else(|| &[][..])
906    }
907
908    pub fn preferred_compression_algs(&self) -> &[CompressionAlgorithm] {
909        self.config()
910            .and_then(|c| {
911                c.hashed_subpackets().find_map(|p| match &p.data {
912                    SubpacketData::PreferredCompressionAlgorithms(d) => Some(&d[..]),
913                    _ => None,
914                })
915            })
916            .unwrap_or_else(|| &[][..])
917    }
918
919    pub fn key_server_prefs(&self) -> &[u8] {
920        self.config()
921            .and_then(|c| {
922                c.hashed_subpackets().find_map(|p| match &p.data {
923                    SubpacketData::KeyServerPreferences(d) => Some(&d[..]),
924                    _ => None,
925                })
926            })
927            .unwrap_or_else(|| &[][..])
928    }
929
930    pub fn key_flags(&self) -> KeyFlags {
931        self.config()
932            .and_then(|c| {
933                c.hashed_subpackets().find_map(|p| match &p.data {
934                    SubpacketData::KeyFlags(flags) => Some(flags.clone()),
935                    _ => None,
936                })
937            })
938            .unwrap_or_default()
939    }
940
941    pub fn features(&self) -> Option<&Features> {
942        self.config().and_then(|c| {
943            c.hashed_subpackets().find_map(|p| match &p.data {
944                SubpacketData::Features(feat) => Some(feat),
945                _ => None,
946            })
947        })
948    }
949
950    pub fn revocation_reason_code(&self) -> Option<&RevocationCode> {
951        self.config().and_then(|c| {
952            c.hashed_subpackets().find_map(|p| match &p.data {
953                SubpacketData::RevocationReason(code, _) => Some(code),
954                _ => None,
955            })
956        })
957    }
958
959    pub fn revocation_reason_string(&self) -> Option<&Bytes> {
960        self.config().and_then(|c| {
961            c.hashed_subpackets().find_map(|p| match &p.data {
962                SubpacketData::RevocationReason(_, reason) => Some(reason),
963                _ => None,
964            })
965        })
966    }
967
968    pub fn is_primary(&self) -> bool {
969        self.config()
970            .and_then(|c| {
971                c.hashed_subpackets().find_map(|p| match &p.data {
972                    SubpacketData::IsPrimary(d) => Some(*d),
973                    _ => None,
974                })
975            })
976            .unwrap_or(false)
977    }
978
979    pub fn is_revocable(&self) -> bool {
980        self.config()
981            .and_then(|c| {
982                c.hashed_subpackets().find_map(|p| match &p.data {
983                    SubpacketData::Revocable(d) => Some(*d),
984                    _ => None,
985                })
986            })
987            .unwrap_or(true)
988    }
989
990    pub fn embedded_signature(&self) -> Option<&Signature> {
991        // We consider data from both the hashed and unhashed area here, because the embedded
992        // signature is inherently cryptographically secured. An attacker can't add a valid
993        // embedded signature, canonicalization will remove any invalid embedded signature
994        // subpackets.
995        if let Some(sub) = self.config().and_then(|c| {
996            c.hashed_subpackets().find_map(|p| match &p.data {
997                SubpacketData::EmbeddedSignature(d) => Some(&**d),
998                _ => None,
999            })
1000        }) {
1001            return Some(sub);
1002        }
1003        if let Some(sub) = self.config().and_then(|c| {
1004            c.unhashed_subpackets().find_map(|p| match &p.data {
1005                SubpacketData::EmbeddedSignature(d) => Some(&**d),
1006                _ => None,
1007            })
1008        }) {
1009            return Some(sub);
1010        }
1011
1012        None
1013    }
1014
1015    pub fn preferred_key_server(&self) -> Option<&str> {
1016        self.config().and_then(|c| {
1017            c.hashed_subpackets().find_map(|p| match &p.data {
1018                SubpacketData::PreferredKeyServer(d) => Some(d.as_str()),
1019                _ => None,
1020            })
1021        })
1022    }
1023
1024    pub fn notations(&self) -> Vec<&Notation> {
1025        self.config()
1026            .map(|c| {
1027                c.hashed_subpackets()
1028                    .filter_map(|p| match &p.data {
1029                        SubpacketData::Notation(d) => Some(d),
1030                        _ => None,
1031                    })
1032                    .collect::<Vec<_>>()
1033            })
1034            .unwrap_or_default()
1035    }
1036
1037    pub fn revocation_key(&self) -> Option<&types::RevocationKey> {
1038        self.config().and_then(|c| {
1039            c.hashed_subpackets().find_map(|p| match &p.data {
1040                SubpacketData::RevocationKey(d) => Some(d),
1041                _ => None,
1042            })
1043        })
1044    }
1045
1046    /// Gets the user id of the signer
1047    ///
1048    /// Note that the user id may not be valid utf-8, if it was created
1049    /// using a different encoding. But since the RFC describes every
1050    /// text as utf-8 it is up to the caller whether to error on non utf-8 data.
1051    pub fn signers_userid(&self) -> Option<&Bytes> {
1052        self.config().and_then(|c| {
1053            c.hashed_subpackets().find_map(|p| match &p.data {
1054                SubpacketData::SignersUserID(d) => Some(d),
1055                _ => None,
1056            })
1057        })
1058    }
1059
1060    pub fn policy_uri(&self) -> Option<&str> {
1061        self.config().and_then(|c| {
1062            c.hashed_subpackets().find_map(|p| match &p.data {
1063                SubpacketData::PolicyURI(d) => Some(d.as_ref()),
1064                _ => None,
1065            })
1066        })
1067    }
1068
1069    pub fn trust_signature(&self) -> Option<(u8, u8)> {
1070        self.config().and_then(|c| {
1071            c.hashed_subpackets().find_map(|p| match &p.data {
1072                SubpacketData::TrustSignature(depth, value) => Some((*depth, *value)),
1073                _ => None,
1074            })
1075        })
1076    }
1077
1078    pub fn regular_expression(&self) -> Option<&Bytes> {
1079        self.config().and_then(|c| {
1080            c.hashed_subpackets().find_map(|p| match &p.data {
1081                SubpacketData::RegularExpression(d) => Some(d),
1082                _ => None,
1083            })
1084        })
1085    }
1086
1087    pub fn exportable_certification(&self) -> bool {
1088        self.config()
1089            .and_then(|c| {
1090                c.hashed_subpackets().find_map(|p| match &p.data {
1091                    SubpacketData::ExportableCertification(d) => Some(*d),
1092                    _ => None,
1093                })
1094            })
1095            .unwrap_or(true)
1096    }
1097}
1098
1099/// The version of a [`Signature`] packet
1100#[derive(derive_more::Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, IntoPrimitive)]
1101#[repr(u8)]
1102pub enum SignatureVersion {
1103    /// Deprecated
1104    V2 = 2,
1105    V3 = 3,
1106    V4 = 4,
1107    V5 = 5,
1108    V6 = 6,
1109
1110    #[num_enum(catch_all)]
1111    Other(#[debug("0x{:x}", _0)] u8),
1112}
1113
1114#[allow(clippy::derivable_impls)]
1115impl Default for SignatureVersion {
1116    fn default() -> Self {
1117        Self::V4
1118    }
1119}
1120
1121/// A signature type defines the meaning of an OpenPGP [`Signature`].
1122///
1123/// The signature type is part of the [`SignatureConfig`] metadata.
1124///
1125/// OpenPGP signatures over data use either [`SignatureType::Binary`] or [`SignatureType::Text`].
1126///
1127/// Most other signature types are used to form certificates (aka OpenPGP public keys), e.g.
1128/// to associate subkeys with a primary key, bind identities to a certificate, and specify
1129/// various certificate metadata such as expiration/revocation status, and algorithm preferences.
1130///
1131/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-signature-types>
1132#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1133#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
1134#[repr(u8)]
1135pub enum SignatureType {
1136    /// Signature of a binary document.
1137    /// This means the signer owns it, created it, or certifies that it has not been modified.
1138    Binary = 0x00,
1139    /// Signature of a canonical text document.
1140    /// This means the signer owns it, created it, or certifies that it
1141    /// has not been modified.  The signature is calculated over the text
1142    /// data with its line endings converted to `<CR><LF>`.
1143    Text = 0x01,
1144    /// Standalone signature.
1145    /// This signature is a signature of only its own subpacket contents.
1146    /// It is calculated identically to a signature over a zero-length
1147    /// binary document.  Note that it doesn't make sense to have a V3 standalone signature.
1148    Standalone = 0x02,
1149    /// Generic certification of a User ID and Public-Key packet.
1150    /// The issuer of this certification does not make any particular
1151    /// assertion as to how well the certifier has checked that the owner
1152    /// of the key is in fact the person described by the User ID.
1153    CertGeneric = 0x10,
1154    /// Persona certification of a User ID and Public-Key packet.
1155    /// The issuer of this certification has not done any verification of
1156    /// the claim that the owner of this key is the User ID specified.
1157    CertPersona = 0x11,
1158    /// Casual certification of a User ID and Public-Key packet.
1159    /// The issuer of this certification has done some casual
1160    /// verification of the claim of identity.
1161    CertCasual = 0x12,
1162    /// Positive certification of a User ID and Public-Key packet.
1163    /// The issuer of this certification has done substantial
1164    /// verification of the claim of identity.
1165    ///
1166    /// Most OpenPGP implementations make their "key signatures" as 0x10
1167    /// certifications.  Some implementations can issue 0x11-0x13
1168    /// certifications, but few differentiate between the types.
1169    CertPositive = 0x13,
1170    /// Subkey Binding Signature
1171    /// This signature is a statement by the top-level signing key that
1172    /// indicates that it owns the subkey.  This signature is calculated
1173    /// directly on the primary key and subkey, and not on any User ID or
1174    /// other packets.  A signature that binds a signing subkey MUST have
1175    /// an Embedded Signature subpacket in this binding signature that
1176    /// contains a 0x19 signature made by the signing subkey on the
1177    /// primary key and subkey.
1178    SubkeyBinding = 0x18,
1179    /// Primary Key Binding Signature
1180    /// This signature is a statement by a signing subkey, indicating
1181    /// that it is owned by the primary key and subkey.  This signature
1182    /// is calculated the same way as a 0x18 signature: directly on the
1183    /// primary key and subkey, and not on any User ID or other packets.
1184    KeyBinding = 0x19,
1185    /// Signature directly on a key
1186    /// This signature is calculated directly on a key.  It binds the
1187    /// information in the Signature subpackets to the key, and is
1188    /// appropriate to be used for subpackets that provide information
1189    /// about the key, such as the Revocation Key subpacket.  It is also
1190    /// appropriate for statements that non-self certifiers want to make
1191    /// about the key itself, rather than the binding between a key and a name.
1192    Key = 0x1F,
1193    /// Key revocation signature
1194    /// The signature is calculated directly on the key being revoked.  A
1195    /// revoked key is not to be used.  Only revocation signatures by the
1196    /// key being revoked, or by an authorized revocation key, should be
1197    /// considered valid revocation signatures.
1198    KeyRevocation = 0x20,
1199    /// Subkey revocation signature
1200    /// The signature is calculated directly on the subkey being revoked.
1201    /// A revoked subkey is not to be used.  Only revocation signatures
1202    /// by the top-level signature key that is bound to this subkey, or
1203    /// by an authorized revocation key, should be considered valid
1204    /// revocation signatures.
1205    SubkeyRevocation = 0x28,
1206    /// Certification revocation signature
1207    /// This signature revokes an earlier User ID certification signature
1208    /// (signature class 0x10 through 0x13) or direct-key signature
1209    /// (0x1F).  It should be issued by the same key that issued the
1210    /// revoked signature or an authorized revocation key.  The signature
1211    /// is computed over the same data as the certificate that it
1212    /// revokes, and should have a later creation date than that
1213    /// certificate.
1214    CertRevocation = 0x30,
1215    /// Timestamp signature.
1216    /// This signature is only meaningful for the timestamp contained in
1217    /// it.
1218    Timestamp = 0x40,
1219    /// Third-Party Confirmation signature.
1220    /// This signature is a signature over some other OpenPGP Signature
1221    /// packet(s).  It is analogous to a notary seal on the signed data.
1222    /// A third-party signature SHOULD include Signature Target
1223    /// subpacket(s) to give easy identification.  Note that we really do
1224    /// mean SHOULD.  There are plausible uses for this (such as a blind
1225    /// party that only sees the signature, not the key or source
1226    /// document) that cannot include a target subpacket.
1227    ThirdParty = 0x50,
1228
1229    #[num_enum(catch_all)]
1230    Other(#[cfg_attr(test, proptest(strategy = "0x51u8.."))] u8),
1231}
1232
1233pub const CERTIFICATION_SIGNATURE_TYPES: &[SignatureType] = &[
1234    SignatureType::CertPositive,
1235    SignatureType::CertGeneric,
1236    SignatureType::CertCasual,
1237    SignatureType::CertPersona,
1238];
1239
1240/// Key Flags signature subpacket
1241///
1242/// A key flag is a semantical annotation to specify which OpenPGP operations a component key
1243/// is intended for.
1244///
1245/// Key flags usually consist of only 1 byte, but the specification allows extension of the field,
1246/// making it potentially arbitrarily long.
1247/// Fields that are currently reserved in the specification can make Key Flags up to 2 bytes long.
1248///
1249/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1250#[derive(Clone, PartialEq, Eq, Debug)]
1251pub struct KeyFlags {
1252    /// Handles the first two bytes.
1253    known: KnownKeyFlags,
1254    /// Any additional key flag bytes.
1255    rest: Option<Bytes>,
1256    /// Need to store this, to fully roundtrip..
1257    original_len: usize,
1258}
1259
1260impl Default for KeyFlags {
1261    fn default() -> Self {
1262        Self {
1263            known: KnownKeyFlags::default(),
1264            rest: None,
1265            original_len: 1,
1266        }
1267    }
1268}
1269
1270impl KeyFlags {
1271    /// Parse the key flags from the given buffer.
1272    pub fn try_from_reader<B: BufRead>(mut reader: B) -> Result<Self> {
1273        let mut buf = reader.rest()?.freeze();
1274        let remaining = buf.len();
1275
1276        if remaining == 0 {
1277            return Ok(Self {
1278                known: KnownKeyFlags::default(),
1279                rest: None,
1280                original_len: remaining,
1281            });
1282        }
1283        if remaining == 1 {
1284            let known = KnownKeyFlags::from_bits(buf.read_u8()? as u16);
1285            return Ok(Self {
1286                known,
1287                rest: None,
1288                original_len: remaining,
1289            });
1290        }
1291        if remaining == 2 {
1292            let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1293            return Ok(Self {
1294                known,
1295                rest: None,
1296                original_len: remaining,
1297            });
1298        }
1299        let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1300        let rest = Some(buf.rest());
1301        Ok(Self {
1302            known,
1303            rest,
1304            original_len: remaining,
1305        })
1306    }
1307
1308    pub fn set_certify(&mut self, val: bool) {
1309        self.known.set_certify(val);
1310    }
1311    pub fn set_encrypt_comms(&mut self, val: bool) {
1312        self.known.set_encrypt_comms(val);
1313    }
1314    pub fn set_encrypt_storage(&mut self, val: bool) {
1315        self.known.set_encrypt_storage(val);
1316    }
1317    pub fn set_sign(&mut self, val: bool) {
1318        self.known.set_sign(val);
1319    }
1320    pub fn set_shared(&mut self, val: bool) {
1321        self.known.set_shared(val);
1322    }
1323    pub fn set_authentication(&mut self, val: bool) {
1324        self.known.set_authentication(val);
1325    }
1326    #[cfg(feature = "draft-wussler-openpgp-forwarding")]
1327    pub fn set_draft_decrypt_forwarded(&mut self, val: bool) {
1328        self.known.set_draft_decrypt_forwarded(val);
1329    }
1330    pub fn set_group(&mut self, val: bool) {
1331        self.known.set_group(val);
1332    }
1333
1334    /// Sets reserved flag 0x0004 also known as ADSK flag.
1335    ///
1336    /// It is a reserved flag also known as ADSK flag
1337    /// since GnuPG 2.4.1 uses it to support
1338    /// proprietary Additional Decryption SubKey feature:
1339    /// <https://www.gnupg.org/blog/20230321-adsk.html>
1340    pub fn set_adsk(&mut self, val: bool) {
1341        self.known.set_adsk(val);
1342    }
1343
1344    pub fn set_timestamping(&mut self, val: bool) {
1345        self.known.set_timestamping(val);
1346    }
1347
1348    pub fn certify(&self) -> bool {
1349        self.known.certify()
1350    }
1351
1352    pub fn encrypt_comms(&self) -> bool {
1353        self.known.encrypt_comms()
1354    }
1355
1356    pub fn encrypt_storage(&self) -> bool {
1357        self.known.encrypt_storage()
1358    }
1359
1360    pub fn sign(&self) -> bool {
1361        self.known.sign()
1362    }
1363
1364    pub fn shared(&self) -> bool {
1365        self.known.shared()
1366    }
1367
1368    pub fn authentication(&self) -> bool {
1369        self.known.authentication()
1370    }
1371
1372    /// Draft key flag: "This key may be used for forwarded communication"
1373    ///
1374    /// Ref <https://datatracker.ietf.org/doc/html/draft-wussler-openpgp-forwarding#name-key-flag-0x40>
1375    pub fn draft_decrypt_forwarded(&self) -> bool {
1376        self.known.draft_decrypt_forwarded()
1377    }
1378
1379    pub fn group(&self) -> bool {
1380        self.known.group()
1381    }
1382
1383    /// Returns the value of Reserved (ADSK) flag.
1384    ///
1385    /// RFC 9580 describes this flag as "Reserved (ADSK)" in
1386    /// <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1387    ///
1388    /// GnuPG 2.4.1 uses this reserved flag to support
1389    /// proprietary Additional Decryption SubKey feature:
1390    /// <https://www.gnupg.org/blog/20230321-adsk.html>
1391    pub fn adsk(&self) -> bool {
1392        self.known.adsk()
1393    }
1394
1395    pub fn timestamping(&self) -> bool {
1396        self.known.timestamping()
1397    }
1398}
1399
1400impl Serialize for KeyFlags {
1401    fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1402        if self.original_len == 0 {
1403            return Ok(());
1404        }
1405
1406        let [a, b] = self.known.into_bits().to_le_bytes();
1407        writer.write_u8(a)?;
1408
1409        if self.original_len > 1 || b != 0 {
1410            writer.write_u8(b)?;
1411        }
1412
1413        if let Some(ref rest) = self.rest {
1414            writer.write_all(rest)?;
1415        }
1416        Ok(())
1417    }
1418
1419    fn write_len(&self) -> usize {
1420        if self.original_len == 0 {
1421            return 0;
1422        }
1423        let mut sum = 0;
1424        let [_, b] = self.known.into_bits().to_le_bytes();
1425        if self.original_len > 1 || b > 0 {
1426            sum += 2;
1427        } else {
1428            sum += 1;
1429        }
1430
1431        if let Some(ref rest) = self.rest {
1432            sum += rest.len();
1433        }
1434        sum
1435    }
1436}
1437
1438/// Encodes the known fields of a [`KeyFlags`].
1439///
1440/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1441#[bitfield(u16, order = lsb)]
1442#[derive(PartialEq, Eq, Copy, Clone)]
1443pub struct KnownKeyFlags {
1444    #[bits(1)]
1445    certify: bool,
1446    #[bits(1)]
1447    sign: bool,
1448    #[bits(1)]
1449    encrypt_comms: bool,
1450    #[bits(1)]
1451    encrypt_storage: bool,
1452    #[bits(1)]
1453    shared: bool,
1454    #[bits(1)]
1455    authentication: bool,
1456    #[bits(1)]
1457    draft_decrypt_forwarded: bool,
1458    #[bits(1)]
1459    group: bool,
1460    #[bits(2)]
1461    _padding1: u8,
1462
1463    /// Non-standard Additional Decryption SubKey flag
1464    ///
1465    /// It is described as "Reserved (ADSK)" in
1466    /// <https://www.rfc-editor.org/rfc/rfc9580.html#name-key-flags>
1467    ///
1468    /// GnuPG 2.4.1 uses this reserved flag to support
1469    /// proprietary Additional Decryption SubKey feature:
1470    /// <https://www.gnupg.org/blog/20230321-adsk.html>
1471    #[bits(1)]
1472    adsk: bool,
1473    #[bits(1)]
1474    timestamping: bool,
1475    #[bits(4)]
1476    _padding2: u8,
1477}
1478
1479/// Features signature subpacket.
1480///
1481/// The Features subpacket denotes which advanced OpenPGP features a user's implementation
1482/// supports, mainly as a signal to communication peers.
1483///
1484/// Features are encoded as "N octets of flags", but currently typically use 1 byte.
1485/// (Only the first 4 bits have been specified so far)
1486///
1487/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-features>
1488#[derive(Clone, PartialEq, Eq, Debug)]
1489pub struct Features {
1490    /// Handles the first byte.
1491    /// Can be None to encode Features subpackets that are 0 byte long.
1492    first: Option<KnownFeatures>,
1493
1494    /// Any additional features bytes.
1495    /// (Must be empty if "known" is None.)
1496    rest: Vec<u8>,
1497}
1498
1499impl Default for Features {
1500    fn default() -> Self {
1501        Self {
1502            first: Some(KnownFeatures::default()),
1503            rest: vec![],
1504        }
1505    }
1506}
1507
1508impl From<&[u8]> for Features {
1509    fn from(value: &[u8]) -> Self {
1510        match value.len() {
1511            0 => Self {
1512                first: None,
1513                rest: vec![],
1514            },
1515            _ => Self {
1516                first: Some(KnownFeatures(value[0])),
1517                rest: value[1..].to_vec(),
1518            },
1519        }
1520    }
1521}
1522
1523impl From<&Features> for Vec<u8> {
1524    fn from(value: &Features) -> Self {
1525        let mut v = vec![];
1526        value.to_writer(&mut v).expect("vec");
1527        v
1528    }
1529}
1530
1531impl From<KnownFeatures> for Features {
1532    fn from(value: KnownFeatures) -> Self {
1533        Self {
1534            first: Some(value),
1535            rest: vec![],
1536        }
1537    }
1538}
1539
1540impl Features {
1541    pub fn new() -> Self {
1542        Self::default()
1543    }
1544
1545    pub fn seipd_v1(&self) -> bool {
1546        match self.first {
1547            Some(k) => k.seipd_v1(),
1548            None => false,
1549        }
1550    }
1551
1552    pub fn set_seipd_v1(&mut self, val: bool) {
1553        if self.first.is_none() {
1554            self.first = Some(KnownFeatures::default());
1555        }
1556
1557        // Should always be Some!
1558        if let Some(k) = self.first.as_mut() {
1559            k.set_seipd_v1(val);
1560        }
1561    }
1562
1563    pub fn seipd_v2(&self) -> bool {
1564        match self.first {
1565            Some(k) => k.seipd_v2(),
1566            None => false,
1567        }
1568    }
1569
1570    pub fn set_seipd_v2(&mut self, val: bool) {
1571        if self.first.is_none() {
1572            self.first = Some(KnownFeatures::default());
1573        }
1574
1575        // Should always be Some!
1576        if let Some(k) = self.first.as_mut() {
1577            k.set_seipd_v2(val);
1578        }
1579    }
1580}
1581
1582impl Serialize for Features {
1583    fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1584        if let Some(k) = self.first {
1585            writer.write_u8(k.0)?;
1586            writer.write_all(&self.rest)?;
1587        }
1588
1589        Ok(())
1590    }
1591
1592    fn write_len(&self) -> usize {
1593        if self.first.is_none() {
1594            0
1595        } else {
1596            1 + self.rest.len()
1597        }
1598    }
1599}
1600
1601/// Encodes the first byte of a [`Features`].
1602///
1603/// Ref <https://www.rfc-editor.org/rfc/rfc9580.html#name-features>
1604#[bitfield(u8)]
1605#[derive(PartialEq, Eq, Copy, Clone)]
1606pub struct KnownFeatures {
1607    /// Support for "Version 1 Symmetrically Encrypted and Integrity Protected Data packet"
1608    #[bits(1)]
1609    seipd_v1: bool,
1610
1611    /// Not standardized in OpenPGP, but used in the LibrePGP fork.
1612    /// Signals support for GnuPG-specific "OCB" encryption packet format.
1613    #[bits(1)]
1614    _libre_ocb: u8,
1615
1616    /// Not standardized in OpenPGP, but used in the LibrePGP fork.
1617    /// Semantics unclear.
1618    #[bits(1)]
1619    _libre_v5_keys: u8,
1620
1621    /// Support for "Version 2 Symmetrically Encrypted and Integrity Protected Data packet"
1622    #[bits(1)]
1623    seipd_v2: bool,
1624
1625    #[bits(4)]
1626    _padding: u8,
1627}
1628
1629/// Notation Data signature subpacket
1630///
1631/// Used as the payload of a [`SubpacketData::Notation`].
1632///
1633/// This subpacket describes a "notation" on the signature that the issuer wishes to make.
1634/// The notation has a name and a value, each of which are strings of octets.
1635/// There may be more than one notation in a signature.
1636/// Notations can be used for any extension the issuer of the signature cares to make.
1637///
1638/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-notation-data>
1639#[derive(Debug, PartialEq, Eq, Clone)]
1640pub struct Notation {
1641    pub readable: bool,
1642    pub name: Bytes,
1643    pub value: Bytes,
1644}
1645
1646/// Value of a [`SubpacketData::RevocationReason`] signature subpacket
1647///
1648/// See <https://www.rfc-editor.org/rfc/rfc9580.html#name-reason-for-revocation>
1649#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1650#[repr(u8)]
1651pub enum RevocationCode {
1652    /// No reason specified (key revocations or cert revocations)
1653    NoReason = 0,
1654    /// Key is superseded (key revocations)
1655    KeySuperseded = 1,
1656    /// Key material has been compromised (key revocations)
1657    KeyCompromised = 2,
1658    /// Key is retired and no longer used (key revocations)
1659    KeyRetired = 3,
1660    /// User ID information is no longer valid (cert revocations)
1661    CertUserIdInvalid = 32,
1662
1663    /// Private Use range (from OpenPGP)
1664    Private100 = 100,
1665    Private101 = 101,
1666    Private102 = 102,
1667    Private103 = 103,
1668    Private104 = 104,
1669    Private105 = 105,
1670    Private106 = 106,
1671    Private107 = 107,
1672    Private108 = 108,
1673    Private109 = 109,
1674    Private110 = 110,
1675
1676    /// Undefined code
1677    #[num_enum(catch_all)]
1678    Other(u8),
1679}
1680
1681impl PacketTrait for Signature {
1682    fn packet_header(&self) -> &PacketHeader {
1683        &self.packet_header
1684    }
1685}
1686
1687pub(super) fn serialize_for_hashing<K: KeyDetails + Serialize>(
1688    key: &K,
1689    hasher: &mut Box<dyn DynDigest + Send>,
1690) -> Result<()> {
1691    let key_len = key.write_len();
1692
1693    let mut writer = WriteHasher(hasher);
1694
1695    // old style packet header for the key
1696    match key.version() {
1697        KeyVersion::V2 | KeyVersion::V3 | KeyVersion::V4 => {
1698            // When a v4 signature is made over a key, the hash data starts with the octet 0x99,
1699            // followed by a two-octet length of the key, and then the body of the key packet.
1700            writer.write_u8(0x99)?;
1701            writer.write_u16::<BigEndian>(key_len.try_into()?)?;
1702        }
1703
1704        KeyVersion::V6 => {
1705            // When a v6 signature is made over a key, the hash data starts with the salt
1706            // [NOTE: the salt is hashed in packet/signature/config.rs],
1707
1708            // then octet 0x9B, followed by a four-octet length of the key,
1709            // and then the body of the key packet.
1710            writer.write_u8(0x9b)?;
1711            writer.write_u32::<BigEndian>(key_len.try_into()?)?;
1712        }
1713
1714        v => unimplemented_err!("key version {:?}", v),
1715    }
1716
1717    key.to_writer(&mut writer)?;
1718
1719    Ok(())
1720}
1721
1722#[cfg(test)]
1723mod tests {
1724    use std::io::Cursor;
1725
1726    use bytes::BytesMut;
1727
1728    use super::*;
1729    use crate::packet::SubpacketType;
1730
1731    /// keyflags being all zeros..are special
1732    #[test]
1733    fn test_keyflags_crazy_versions() {
1734        for i in 0..1024 {
1735            println!("size {i}");
1736            // I write this with pain...
1737            let source = BytesMut::zeroed(i).freeze();
1738            let flags = KeyFlags::try_from_reader(&source[..]).unwrap();
1739            assert_eq!(&flags.to_bytes().unwrap(), &source);
1740        }
1741    }
1742
1743    #[test]
1744    fn test_keyflags_1_byte() {
1745        let flags: KeyFlags = Default::default();
1746        assert_eq!(flags.to_bytes().unwrap(), vec![0x00]);
1747
1748        let mut flags = KeyFlags::default();
1749        flags.set_certify(true);
1750        assert!(flags.certify());
1751        assert_eq!(flags.to_bytes().unwrap(), vec![0x01]);
1752
1753        let mut flags = KeyFlags::default();
1754        flags.set_sign(true);
1755        assert_eq!(flags.to_bytes().unwrap(), vec![0x02]);
1756
1757        let mut flags = KeyFlags::default();
1758        flags.set_encrypt_comms(true);
1759        assert_eq!(flags.to_bytes().unwrap(), vec![0x04]);
1760
1761        let mut flags = KeyFlags::default();
1762        flags.set_encrypt_storage(true);
1763        assert_eq!(flags.to_bytes().unwrap(), vec![0x08]);
1764
1765        let mut flags = KeyFlags::default();
1766        flags.set_shared(true);
1767        assert_eq!(flags.to_bytes().unwrap(), vec![0x10]);
1768
1769        let mut flags = KeyFlags::default();
1770        flags.set_authentication(true);
1771        assert_eq!(flags.to_bytes().unwrap(), vec![0x20]);
1772
1773        let mut flags = KeyFlags::default();
1774        flags.set_group(true);
1775        assert_eq!(flags.to_bytes().unwrap(), vec![0x80]);
1776
1777        let mut flags = KeyFlags::default();
1778        flags.set_certify(true);
1779        flags.set_sign(true);
1780        assert_eq!(flags.to_bytes().unwrap(), vec![0x03]);
1781    }
1782
1783    #[test]
1784    fn test_keyflags_2_bytes() {
1785        let mut flags: KeyFlags = Default::default();
1786        flags.set_adsk(true);
1787        assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x04]);
1788
1789        let mut flags: KeyFlags = Default::default();
1790        flags.set_timestamping(true);
1791        assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x08]);
1792
1793        let mut flags: KeyFlags = Default::default();
1794        flags.set_timestamping(true);
1795        flags.set_certify(true);
1796        flags.set_sign(true);
1797
1798        assert_eq!(flags.to_bytes().unwrap(), vec![0x03, 0x08]);
1799    }
1800
1801    #[test]
1802    fn test_features() {
1803        use crate::packet::Features;
1804
1805        // deserialize/serialize, getters
1806        {
1807            let empty: Features = (&[][..]).into();
1808            assert_eq!(empty.seipd_v1(), false);
1809            assert_eq!(empty.seipd_v2(), false);
1810
1811            assert_eq!(empty.write_len(), 0);
1812            let mut out = vec![];
1813            empty.to_writer(&mut out).expect("write");
1814            assert!(out.is_empty());
1815        }
1816        {
1817            let seipdv1: Features = (&[0x01][..]).into();
1818            assert_eq!(seipdv1.seipd_v1(), true);
1819            assert_eq!(seipdv1.seipd_v2(), false);
1820
1821            assert_eq!(seipdv1.write_len(), 1);
1822            let mut out = vec![];
1823            seipdv1.to_writer(&mut out).expect("write");
1824            assert_eq!(out, vec![0x01]);
1825        }
1826        {
1827            let allbits: Features = (&[0xff][..]).into();
1828            assert_eq!(allbits.seipd_v1(), true);
1829            assert_eq!(allbits.seipd_v2(), true);
1830
1831            assert_eq!(allbits.write_len(), 1);
1832            let mut out = vec![];
1833            allbits.to_writer(&mut out).expect("write");
1834            assert_eq!(out, vec![0xff]);
1835        }
1836        {
1837            let three_bytes: Features = (&[0x09, 0xaa, 0xbb][..]).into();
1838            assert_eq!(three_bytes.seipd_v1(), true);
1839            assert_eq!(three_bytes.seipd_v2(), true);
1840
1841            assert_eq!(three_bytes.write_len(), 3);
1842            let mut out = vec![];
1843            three_bytes.to_writer(&mut out).expect("write");
1844            assert_eq!(out, vec![0x09, 0xaa, 0xbb]);
1845        }
1846
1847        // setters
1848        {
1849            let mut empty: Features = (&[][..]).into();
1850            assert!(Vec::<u8>::from(&empty).is_empty());
1851
1852            empty.set_seipd_v1(true);
1853            assert_eq!(Vec::<u8>::from(&empty), vec![0x01]);
1854        }
1855        {
1856            let mut default = Features::default();
1857            assert_eq!(Vec::<u8>::from(&default), vec![0x00]);
1858
1859            default.set_seipd_v1(true);
1860            assert_eq!(Vec::<u8>::from(&default), vec![0x01]);
1861
1862            default.set_seipd_v2(true);
1863            assert_eq!(Vec::<u8>::from(&default), vec![0x09]);
1864        }
1865        {
1866            let mut allbits: Features = (&[0xff][..]).into();
1867
1868            allbits.set_seipd_v1(false);
1869            assert_eq!(Vec::<u8>::from(&allbits), vec![0xfe]);
1870
1871            allbits.set_seipd_v2(false);
1872            assert_eq!(Vec::<u8>::from(&allbits), vec![0xf6]);
1873        }
1874        {
1875            let mut three_bytes: Features = (&[0x00, 0xaa, 0xbb][..]).into();
1876            three_bytes.set_seipd_v2(true);
1877            assert_eq!(Vec::<u8>::from(&three_bytes), vec![0x08, 0xaa, 0xbb]);
1878        }
1879    }
1880
1881    #[test]
1882    fn test_critical() {
1883        use SubpacketType::*;
1884        let cases = [
1885            SignatureCreationTime,
1886            SignatureExpirationTime,
1887            ExportableCertification,
1888            TrustSignature,
1889            RegularExpression,
1890            Revocable,
1891            KeyExpirationTime,
1892            PreferredSymmetricAlgorithms,
1893            RevocationKey,
1894            IssuerKeyId,
1895            Notation,
1896            PreferredHashAlgorithms,
1897            PreferredCompressionAlgorithms,
1898            KeyServerPreferences,
1899            PreferredKeyServer,
1900            PrimaryUserId,
1901            PolicyURI,
1902            KeyFlags,
1903            SignersUserID,
1904            RevocationReason,
1905            Features,
1906            SignatureTarget,
1907            EmbeddedSignature,
1908            IssuerFingerprint,
1909            PreferredAead,
1910            Experimental(101),
1911            Other(95),
1912        ];
1913        for case in cases {
1914            assert_eq!(SubpacketType::from_u8(case.as_u8(false)), (case, false));
1915            assert_eq!(SubpacketType::from_u8(case.as_u8(true)), (case, true));
1916        }
1917    }
1918
1919    use proptest::prelude::*;
1920
1921    use crate::composed::DetachedSignature;
1922
1923    impl Arbitrary for KeyFlags {
1924        type Parameters = ();
1925        type Strategy = BoxedStrategy<Self>;
1926
1927        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
1928            proptest::collection::vec(0u8..255, 1..500)
1929                .prop_map(|v| KeyFlags::try_from_reader(&mut &v[..]).unwrap())
1930                .boxed()
1931        }
1932    }
1933
1934    #[test]
1935    fn unhashed_area_modification() {
1936        fn subpacket_type_list(sig: &Signature) -> Vec<SubpacketType> {
1937            sig.config()
1938                .unwrap()
1939                .unhashed_subpackets
1940                .iter()
1941                .map(Subpacket::typ)
1942                .collect()
1943        }
1944
1945        use crate::composed::Deserializable;
1946
1947        let mut sig = DetachedSignature::from_armor_single(Cursor::new(
1948            "-----BEGIN PGP SIGNATURE-----
1949
1950wpoEEBYIAEIFAmheZZEWIQT8Y2QNsPXIvVyHlK1LkdWvyoDDywIbAwIeAQQLCQgH
1951BhUOCgkMCAEWDScJAggCBwIJAQgBBwECGQEACgkQS5HVr8qAw8swhAD/RFBBueDN
1952ClWUWHgCj+FmHElqrUO4YVePdt2KRkniPJ4A/jtOCzD7vZJZs0yP4xQ78PEsUST0
1953pwsJtT3sJB2q5NoA
1954=XphF
1955-----END PGP SIGNATURE-----",
1956        ))
1957        .unwrap()
1958        .0
1959        .signature;
1960
1961        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(154));
1962
1963        sig.unhashed_subpacket_push(
1964            Subpacket::regular(SubpacketData::Notation(Notation {
1965                readable: true,
1966                name: "foo".into(),
1967                value: "bar".into(),
1968            }))
1969            .unwrap(),
1970        )
1971        .unwrap();
1972        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(170));
1973        assert_eq!(
1974            &subpacket_type_list(&sig),
1975            &[SubpacketType::IssuerKeyId, SubpacketType::Notation]
1976        );
1977
1978        sig.unhashed_subpacket_insert(
1979            0,
1980            Subpacket::regular(SubpacketData::Notation(Notation {
1981                readable: true,
1982                name: "hello".into(),
1983                value: "world".into(),
1984            }))
1985            .unwrap(),
1986        )
1987        .unwrap();
1988        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
1989        assert_eq!(
1990            &subpacket_type_list(&sig),
1991            &[
1992                SubpacketType::Notation,
1993                SubpacketType::IssuerKeyId,
1994                SubpacketType::Notation
1995            ]
1996        );
1997
1998        sig.unhashed_subpackets_sort_by(|a, b| {
1999            a.typ()
2000                .as_u8(a.is_critical)
2001                .cmp(&b.typ().as_u8(b.is_critical))
2002        });
2003        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
2004        assert_eq!(
2005            &subpacket_type_list(&sig),
2006            &[
2007                SubpacketType::IssuerKeyId,
2008                SubpacketType::Notation,
2009                SubpacketType::Notation
2010            ]
2011        );
2012
2013        sig.unhashed_subpacket_remove(0).unwrap();
2014        assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(180));
2015        assert_eq!(
2016            &subpacket_type_list(&sig),
2017            &[SubpacketType::Notation, SubpacketType::Notation]
2018        );
2019    }
2020
2021    proptest! {
2022        #[test]
2023        fn keyflags_write_len(flags: KeyFlags) {
2024            let mut buf = Vec::new();
2025            flags.to_writer(&mut buf).unwrap();
2026            prop_assert_eq!(buf.len(), flags.write_len());
2027        }
2028
2029        #[test]
2030        fn keyflags_packet_roundtrip(flags: KeyFlags) {
2031            let mut buf = Vec::new();
2032            flags.to_writer(&mut buf).unwrap();
2033            let new_flags = KeyFlags::try_from_reader(&mut &buf[..]).unwrap();
2034            prop_assert_eq!(flags, new_flags);
2035        }
2036    }
2037}