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#[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 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 #[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 #[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 #[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 #[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 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; 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; 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 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 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 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 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 pub fn unhashed_subpacket_remove(&mut self, index: usize) -> Result<Subpacket> {
315 if let InnerSignature::Known { ref mut config, .. } = self.inner {
316 ensure!(
317 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 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 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 pub fn typ(&self) -> Option<SignatureType> {
359 self.config().map(|c| c.typ())
360 }
361
362 pub fn hash_alg(&self) -> Option<HashAlgorithm> {
364 self.config().map(|c| c.hash_alg)
365 }
366
367 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 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 issuer_key_ids.is_empty() && issuer_fps.is_empty() {
396 return true;
397 }
398
399 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 fn check_signature_key_version_alignment(
412 key: &impl KeyDetails,
413 config: &SignatureConfig,
414 ) -> Result<()> {
415 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 pub(crate) fn check_signature_hash_strength(config: &SignatureConfig) -> Result<()> {
438 if config.pub_alg.is_pqc() {
439 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 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 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 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 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 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 {
604 serialize_for_hashing(signee, &mut hasher)?;
606 }
607
608 {
610 let packet_len = id.write_len();
611
612 match config.version() {
613 SignatureVersion::V2 | SignatureVersion::V3 => {
614 }
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 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 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)?; serialize_for_hashing(signee, &mut hasher)?; 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 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)?; serialize_for_hashing(signer, &mut hasher)?; 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 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 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 pub fn is_certification(&self) -> bool {
830 self.config()
831 .map(|c| c.is_certification())
832 .unwrap_or_default()
833 }
834
835 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 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 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#[derive(derive_more::Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, IntoPrimitive)]
1101#[repr(u8)]
1102pub enum SignatureVersion {
1103 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#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1133#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
1134#[repr(u8)]
1135pub enum SignatureType {
1136 Binary = 0x00,
1139 Text = 0x01,
1144 Standalone = 0x02,
1149 CertGeneric = 0x10,
1154 CertPersona = 0x11,
1158 CertCasual = 0x12,
1162 CertPositive = 0x13,
1170 SubkeyBinding = 0x18,
1179 KeyBinding = 0x19,
1185 Key = 0x1F,
1193 KeyRevocation = 0x20,
1199 SubkeyRevocation = 0x28,
1206 CertRevocation = 0x30,
1215 Timestamp = 0x40,
1219 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#[derive(Clone, PartialEq, Eq, Debug)]
1251pub struct KeyFlags {
1252 known: KnownKeyFlags,
1254 rest: Option<Bytes>,
1256 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 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 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 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 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#[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 #[bits(1)]
1472 adsk: bool,
1473 #[bits(1)]
1474 timestamping: bool,
1475 #[bits(4)]
1476 _padding2: u8,
1477}
1478
1479#[derive(Clone, PartialEq, Eq, Debug)]
1489pub struct Features {
1490 first: Option<KnownFeatures>,
1493
1494 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 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 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#[bitfield(u8)]
1605#[derive(PartialEq, Eq, Copy, Clone)]
1606pub struct KnownFeatures {
1607 #[bits(1)]
1609 seipd_v1: bool,
1610
1611 #[bits(1)]
1614 _libre_ocb: u8,
1615
1616 #[bits(1)]
1619 _libre_v5_keys: u8,
1620
1621 #[bits(1)]
1623 seipd_v2: bool,
1624
1625 #[bits(4)]
1626 _padding: u8,
1627}
1628
1629#[derive(Debug, PartialEq, Eq, Clone)]
1640pub struct Notation {
1641 pub readable: bool,
1642 pub name: Bytes,
1643 pub value: Bytes,
1644}
1645
1646#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1650#[repr(u8)]
1651pub enum RevocationCode {
1652 NoReason = 0,
1654 KeySuperseded = 1,
1656 KeyCompromised = 2,
1658 KeyRetired = 3,
1660 CertUserIdInvalid = 32,
1662
1663 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 #[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 match key.version() {
1697 KeyVersion::V2 | KeyVersion::V3 | KeyVersion::V4 => {
1698 writer.write_u8(0x99)?;
1701 writer.write_u16::<BigEndian>(key_len.try_into()?)?;
1702 }
1703
1704 KeyVersion::V6 => {
1705 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 #[test]
1733 fn test_keyflags_crazy_versions() {
1734 for i in 0..1024 {
1735 println!("size {i}");
1736 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 {
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 {
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}