Skip to main content

sequoia_sop/
lib.rs

1//! An implementation of the [Stateless OpenPGP Interface] using [Sequoia PGP].
2//!
3//! SOP is a very high-level, opinionated, and abstract interface for
4//! OpenPGP implementations.  To use it, create an instance using
5//! [`SQOP::default`] or [`SQOP::with_policy`], then use the trait
6//! [`SOP`].
7//!
8//! # Examples
9//!
10//! This example generates a key.
11//!
12//! ```rust
13//! # fn main() -> sop::Result<()> {
14//! use sequoia_sop::{*, sop::*};
15//!
16//! let sop = SQOP::default();
17//!
18//! let alice_sec = sop.generate_key()?
19//!     .userid("Alice Lovelace <alice@openpgp.example>")
20//!     .generate()?
21//!     .to_vec(true)?;
22//! assert!(alice_sec.starts_with(b"-----BEGIN PGP PRIVATE KEY BLOCK-----"));
23//! # Ok(()) }
24//! ```
25//!
26//!   [Stateless OpenPGP Interface]: https://gitlab.com/dkg/openpgp-stateless-cli
27//!   [Sequoia PGP]: https://sequoia-pgp.org
28
29use std::{
30    collections::{BTreeMap, BTreeSet, HashMap},
31    io::{self, Cursor, Write},
32    time::SystemTime,
33};
34
35use sequoia_openpgp as openpgp;
36use openpgp::{
37    armor,
38    cert::prelude::*,
39    parse::{
40        Cookie,
41        Parse,
42        PacketParser,
43        PacketParserResult,
44        buffered_reader::*,
45        stream::*,
46    },
47    packet::prelude::*,
48    policy::{
49        NullPolicy,
50        StandardPolicy,
51    },
52    serialize::{
53        Serialize,
54        stream::{*, padding::Padder},
55    },
56    types::*,
57};
58
59use openpgp::{
60    Cert,
61    KeyID,
62};
63use openpgp::crypto::{self, SessionKey};
64use openpgp::packet::{key, Key, PKESK, SKESK};
65use openpgp::policy::Policy;
66
67// Public re-export for the convenience of end users.
68pub use sop::{self, SOP};
69
70use sop::{
71    *,
72    errors::*,
73    ops::{
74        ArmorLabel,
75        EncryptAs,
76        InlineSignAs,
77        SignAs,
78        SignatureMode,
79        Verification,
80    },
81    plumbing::PasswordsAreHumanReadable,
82};
83
84#[macro_use]
85mod macros;
86mod version;
87
88/// A collection of certs.
89pub struct Certs<'s> {
90    sop: &'s SQOP<'s>,
91    certs: Vec<openpgp::Cert>,
92    source_name: Option<String>,
93}
94
95impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Certs<'s> {
96    fn sop(&self) -> &'s SQOP<'s> {
97        self.sop
98    }
99}
100
101impl<'s> sop::Load<'s, SQOP<'s>> for Certs<'s> {
102    fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
103                   source_name: Option<String>)
104                   -> Result<Self>
105    where
106        Self: Sized,
107    {
108        let sop_error = |e| sop.sop_error(e);
109
110        Ok(Certs {
111            sop,
112            certs: CertParser::from_reader(source).map_err(sop_error)?
113                .collect::<openpgp::Result<Vec<openpgp::Cert>>>()
114                .map_err(sop_error)?,
115            source_name,
116        })
117    }
118
119    fn source_name(&self) -> Option<&str> {
120        self.source_name.as_ref().map(|s| s.as_str())
121    }
122}
123
124impl sop::Save for Certs<'_> {
125    fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
126                 -> Result<()>
127    {
128        let sop_error = |e| self.sop.sop_error(e);
129
130        if self.certs.len() == 1 {
131            let cert = &self.certs[0];
132            if armored {
133                cert.armored().serialize(sink).map_err(sop_error)?;
134            } else {
135                cert.serialize(sink).map_err(sop_error)?;
136            }
137        } else {
138            if armored {
139                let mut armorer =
140                    armor::Writer::new(sink, armor::Kind::PublicKey)?;
141                for cert in &self.certs {
142                    cert.serialize(&mut armorer).map_err(sop_error)?;
143                }
144                armorer.finalize()?;
145            } else {
146                for cert in &self.certs {
147                    cert.serialize(sink).map_err(sop_error)?;
148                }
149            }
150        }
151        Ok(())
152    }
153}
154
155/// A collection of keys.
156pub struct Keys<'s> {
157    sop: &'s SQOP<'s>,
158    keys: Vec<openpgp::Cert>,
159    source_name: Option<String>,
160}
161
162impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Keys<'s> {
163    fn sop(&self) -> &'s SQOP<'s> {
164        self.sop
165    }
166}
167
168impl<'s> sop::Load<'s, SQOP<'s>> for Keys<'s> {
169    fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
170                   source_name: Option<String>)
171                   -> Result<Self>
172    where
173        Self: Sized,
174    {
175        let sop_error = |e| sop.sop_error(e);
176
177        Ok(Keys {
178            sop,
179            keys: CertParser::from_reader(source).map_err(sop_error)?
180                .collect::<openpgp::Result<Vec<openpgp::Cert>>>()
181                .map_err(sop_error)?,
182            source_name,
183        })
184    }
185
186    fn source_name(&self) -> Option<&str> {
187        self.source_name.as_ref().map(|s| s.as_str())
188    }
189}
190
191impl sop::Save for Keys<'_> {
192    fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
193                 -> Result<()>
194    {
195        let sop_error = |e| self.sop.sop_error(e);
196
197        if self.keys.len() == 1 {
198            let key = &self.keys[0];
199            if armored {
200                key.as_tsk().armored().serialize(sink).map_err(sop_error)?;
201            } else {
202                key.as_tsk().serialize(sink).map_err(sop_error)?;
203            }
204        } else {
205            if armored {
206                let mut armorer =
207                    armor::Writer::new(sink, armor::Kind::SecretKey)?;
208                for key in &self.keys {
209                    key.as_tsk().serialize(&mut armorer).map_err(sop_error)?;
210                }
211                armorer.finalize()?;
212            } else {
213                for key in &self.keys {
214                    key.as_tsk().serialize(sink).map_err(sop_error)?;
215                }
216            }
217        }
218        Ok(())
219    }
220}
221
222/// A collection of signatures.
223pub struct Sigs<'s> {
224    sop: &'s SQOP<'s>,
225    data: Vec<u8>,
226    source_name: Option<String>,
227}
228
229impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Sigs<'s> {
230    fn sop(&self) -> &'s SQOP<'s> {
231        self.sop
232    }
233}
234
235impl<'s> sop::Load<'s, SQOP<'s>> for Sigs<'s> {
236    fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
237                   source_name: Option<String>)
238                   -> Result<Self>
239    where
240        Self: Sized,
241    {
242        let mut data = vec![];
243        source.read_to_end(&mut data)?;
244        Ok(Sigs {
245            sop,
246            data,
247            source_name,
248        })
249    }
250
251    fn source_name(&self) -> Option<&str> {
252        self.source_name.as_ref().map(|s| s.as_str())
253    }
254}
255
256impl sop::Save for Sigs<'_> {
257    fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
258                 -> Result<()>
259    {
260        // Happy path: Want armored and it already is.
261        if armored && self.data.starts_with(
262            b"-----BEGIN PGP PUBLIC KEY BLOCK-----")
263        {
264            sink.write_all(&self.data)?;
265            return Ok(());
266        }
267
268        if armored {
269            self.sop.armor()?
270                .data(&mut Cursor::new(&self.data))?
271                .to_writer(sink)?;
272        } else {
273            self.sop.dearmor()?
274                .data(&mut Cursor::new(&self.data))?
275                .to_writer(sink)?;
276        }
277        Ok(())
278    }
279}
280
281/// [`SOP`] implementation based on [Sequoia PGP].
282///
283///   [Sequoia PGP]: https://sequoia-pgp.org
284pub struct SQOP<'s> {
285    policy: &'s dyn openpgp::policy::Policy,
286    debug: bool,
287}
288
289impl Default for SQOP<'_> {
290    fn default() -> Self {
291        const P: &StandardPolicy = &StandardPolicy::new();
292        Self::with_policy(P)
293    }
294}
295
296impl<'s> SQOP<'s> {
297    /// Creates a [`sop::SOP`] implementation with an explicit
298    /// [`sequoia_openpgp::policy::Policy`].
299    ///
300    /// To use the default
301    /// [`sequoia_openpgp::policy::StandardPolicy`], use
302    /// [`SQOP::default`].
303    pub fn with_policy(policy: &'s dyn Policy) -> Self {
304        SQOP {
305            policy,
306            debug: false,
307        }
308    }
309
310    /// A "convenient" function to provide the library context to
311    /// [`sop_error`].
312    fn sop_error(&self, e: anyhow::Error) -> Error {
313        sop_error(self, e)
314    }
315}
316
317impl<'s> sop::SOP<'s> for SQOP<'s> {
318    type Keys = Keys<'s>;
319    type Certs = Certs<'s>;
320    type Sigs = Sigs<'s>;
321
322    fn debug(&mut self, enable: bool) {
323        self.debug = enable;
324    }
325    fn version(&self) -> Result<Box<dyn sop::ops::Version>> {
326        Ok(Box::new(version::Version::default()))
327    }
328    fn sopv_version(&'s self) -> Result<&'static str> {
329        Ok("1.0")
330    }
331    fn generate_key(&'s self)
332        -> Result<Box<dyn sop::ops::GenerateKey<SQOP, Keys> + 's>>
333    {
334        GenerateKey::new(self)
335    }
336    fn change_key_password(&'s self)
337        -> Result<Box<dyn sop::ops::ChangeKeyPassword<SQOP, Keys> + 's>>
338    {
339        ChangeKeyPassword::new(self)
340    }
341    fn revoke_key(&'s self)
342        -> Result<Box<dyn sop::ops::RevokeKey<SQOP<'s>, Certs, Keys> + 's>>
343    {
344        RevokeKey::new(self)
345    }
346    fn extract_cert(&'s self)
347        -> Result<Box<dyn sop::ops::ExtractCert<SQOP, Certs, Keys> + 's>>
348    {
349        ExtractCert::new(self)
350    }
351    fn update_key(&'s self)
352        -> Result<Box<dyn sop::ops::UpdateKey<Self, Self::Certs, Self::Keys> + 's>>
353    {
354        Err(Error::NotImplemented)
355    }
356    fn merge_certs(&'s self)
357        -> Result<Box<dyn sop::ops::MergeCerts<Self, Self::Certs> + 's>>
358    {
359        MergeCerts::new(self)
360    }
361    fn certify_userid(&'s self)
362        -> Result<Box<dyn sop::ops::CertifyUserID<Self, Self::Certs, Self::Keys> + 's>>
363    {
364        CertifyUserID::new(self)
365    }
366    fn validate_userid(&'s self)
367        -> Result<Box<dyn sop::ops::ValidateUserID<Self, Self::Certs> + 's>>
368    {
369        ValidateUserID::new(self)
370    }
371    fn sign(&'s self)
372        -> Result<Box<dyn sop::ops::Sign<SQOP, Keys, Sigs> + 's>>
373    {
374        Sign::new(self)
375    }
376    fn verify(&'s self)
377        -> Result<Box<dyn sop::ops::Verify<SQOP, Certs, Sigs> + 's>>
378    {
379        Verify::new(self)
380    }
381    fn encrypt(&'s self)
382        -> Result<Box<dyn sop::ops::Encrypt<SQOP, Certs, Keys> + 's>> {
383        Encrypt::new(self)
384    }
385    fn decrypt(&'s self)
386        -> Result<Box<dyn sop::ops::Decrypt<SQOP, Certs, Keys> + 's>> {
387        Decrypt::new(self)
388    }
389    fn armor(&'s self) -> Result<Box<dyn sop::ops::Armor + 's>> {
390        Armor::new(self)
391    }
392    fn dearmor(&'s self) -> Result<Box<dyn sop::ops::Dearmor + 's>> {
393        Dearmor::new(self)
394    }
395    fn inline_detach(&'s self)
396        -> Result<Box<dyn sop::ops::InlineDetach<Sigs> + 's>>
397    {
398        InlineDetach::new(self)
399    }
400    fn inline_verify(&'s self)
401        -> Result<Box<dyn sop::ops::InlineVerify<SQOP, Certs> + 's>>
402    {
403        InlineVerify::new(self)
404    }
405    fn inline_sign(&'s self)
406        -> Result<Box<dyn sop::ops::InlineSign<SQOP, Keys> + 's>>
407    {
408        InlineSign::new(self)
409    }
410}
411
412struct GenerateKey<'s> {
413    #[allow(dead_code)]
414    sqop: &'s SQOP<'s>,
415    profile: &'static str,
416    signing_only: bool,
417    with_key_password: Option<Password>,
418    userids: Vec<String>,
419}
420
421impl<'s> GenerateKey<'s> {
422    const PROFILE_RFC9580: &'static str = "rfc9580";
423    const PROFILE_EDDSA: &'static str = "draft-koch-eddsa-for-openpgp-00";
424    const PROFILE_RFC4880: &'static str = "rfc4880";
425    const PROFILE_RFC9980: &'static str = "rfc9980";
426    const PROFILES: &'static [(&'static str, &'static str)] = &[
427        (Self::PROFILE_RFC9580, "use Ed25519/X25519"),
428        (Self::PROFILE_EDDSA, "use EdDSA & ECDH over Cv25519"),
429        (Self::PROFILE_RFC4880, "use RSA with 3072 bit keys"),
430        (Self::PROFILE_RFC9980, "use MLDSA65+Ed25519 & MLKEM768+X25519"),
431    ];
432
433    fn normalize_profile(profile: &str) -> Result<&'static str> {
434        match profile {
435            Self::PROFILE_RFC9580 => Ok(Self::PROFILE_RFC9580),
436            Self::PROFILE_EDDSA => Ok(Self::PROFILE_EDDSA),
437            Self::PROFILE_RFC4880 => Ok(Self::PROFILE_RFC4880),
438            Self::PROFILE_RFC9980 => Ok(Self::PROFILE_RFC9980),
439
440            // The symbolic aliases.
441            "default" => Ok(match openpgp::Profile::default() {
442                openpgp::Profile::RFC4880 => Self::PROFILE_EDDSA,
443                openpgp::Profile::RFC9580 => Self::PROFILE_RFC9580,
444                _ => Self::PROFILE_RFC9580,
445            }),
446            "security" => Ok(Self::PROFILE_RFC9980),
447            "performance" => Ok(Self::PROFILE_RFC9580),
448            "compatibility" => Ok(Self::PROFILE_RFC4880),
449
450            _ => Err(Error::UnsupportedProfile),
451        }
452    }
453
454    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
455        Ok(Box::new(GenerateKey {
456            sqop,
457            profile: Self::normalize_profile("default")?,
458            signing_only: false,
459            with_key_password: Default::default(),
460            userids: Default::default(),
461        }))
462    }
463}
464
465impl<'s> sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> for GenerateKey<'s> {
466    fn list_profiles(&self) -> Vec<(String, String)> {
467        list_profiles(Self::PROFILES, &Self::normalize_profile)
468    }
469
470    fn profile(mut self: Box<Self>, profile: &str)
471               -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
472        self.profile = Self::normalize_profile(profile)?;
473        Ok(self)
474    }
475
476    fn signing_only(mut self: Box<Self>) -> Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's> {
477        self.signing_only = true;
478        self
479    }
480
481    fn with_key_password(mut self: Box<Self>, password: Password)
482                         -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
483        self.with_key_password = Some(password);
484        Ok(self)
485    }
486
487    fn userid(mut self: Box<Self>, userid: &str)
488              -> Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's> {
489        self.userids.push(userid.into());
490        self
491    }
492
493    fn generate(self: Box<Self>) -> Result<Keys<'s>> {
494        let sop_error = |e| self.sqop.sop_error(e);
495
496        let mut builder = CertBuilder::new();
497        builder = builder.add_signing_subkey();
498        if ! self.signing_only {
499            builder = builder.add_subkey(
500                KeyFlags::empty()
501                    .set_storage_encryption()
502                    .set_transport_encryption(),
503                None,
504                None);
505        }
506
507        builder = builder.set_profile(match self.profile {
508            Self::PROFILE_RFC9580 => openpgp::Profile::RFC9580,
509            Self::PROFILE_EDDSA => openpgp::Profile::RFC4880,
510            Self::PROFILE_RFC4880 => openpgp::Profile::RFC4880,
511            Self::PROFILE_RFC9980 => openpgp::Profile::RFC9580,
512            _ => return Err(Error::UnsupportedProfile),
513        }).map_err(sop_error)?;
514
515        builder = builder.set_cipher_suite(match self.profile {
516            Self::PROFILE_RFC9580 => CipherSuite::Cv25519,
517            Self::PROFILE_EDDSA => CipherSuite::Cv25519,
518            Self::PROFILE_RFC4880 => CipherSuite::RSA3k,
519            Self::PROFILE_RFC9980 => CipherSuite::MLDSA65_Ed25519,
520            _ => return Err(Error::UnsupportedProfile),
521        });
522
523        for u in self.userids {
524            builder = builder.add_userid(u);
525        }
526        if let Some(p) = self.with_key_password {
527            builder = builder.set_password(Some(p.normalized().into()));
528        }
529        let (key, _) = builder.generate().map_err(sop_error)?;
530
531        Ok(Keys {
532            sop: self.sqop,
533            keys: vec![key],
534            source_name: None,
535        })
536    }
537}
538
539struct ChangeKeyPassword<'s> {
540    #[allow(dead_code)]
541    sqop: &'s SQOP<'s>,
542    new_password: Option<openpgp::crypto::Password>,
543    old_password: Vec<openpgp::crypto::Password>,
544}
545
546impl<'s> ChangeKeyPassword<'s> {
547    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
548        Ok(Box::new(ChangeKeyPassword {
549            sqop,
550            new_password: None,
551            old_password: vec![],
552        }))
553    }
554}
555
556impl<'s> sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> for ChangeKeyPassword<'s> {
557    fn new_key_password(mut self: Box<Self>, password: Password)
558                        -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
559        self.new_password = Some(password.normalized().into());
560        Ok(self)
561    }
562
563    fn old_key_password(mut self: Box<Self>, password: Password)
564                        -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
565        for p in password.variants() {
566            self.old_password.push(p.into());
567        }
568        Ok(self)
569    }
570
571    fn keys(self: Box<Self>, keys: &Keys) -> Result<Keys<'s>> {
572        let sop_error = |e| self.sqop.sop_error(e);
573
574        let mut result = vec![];
575
576        for key in keys.keys.clone() {
577            let fp = key.fingerprint();
578
579            // Extract the key packets, starting with the unencrypted
580            // ones.
581            let mut key_packets =
582                key.keys().unencrypted_secret()
583                .map(|ka| ka.key().clone())
584                .collect::<Vec<_>>();
585
586            // Then the encrypted ones, decrypting them on the way.
587            for locked_key in key.keys().secret()
588                .filter(|ka| ka.key().secret().is_encrypted())
589                .map(|ka| ka.key())
590            {
591                let mut unlocked = false;
592
593                for p in &self.old_password {
594                    if let Ok(k) = locked_key.clone().decrypt_secret(p) {
595                        key_packets.push(k);
596                        unlocked = true;
597                        break;
598                    }
599                }
600
601                if ! unlocked {
602                    return Err(Error::KeyIsProtected);
603                }
604            }
605
606            // Maybe encrypt them.
607            if let Some(p) = &self.new_password {
608                for k in std::mem::take(&mut key_packets) {
609                    key_packets.push(k.encrypt_secret(&p).map_err(sop_error)?);
610                }
611            }
612
613            // And update the key packets in the cert.
614            let (key, _changed) =
615                key.insert_packets(
616                    key_packets.into_iter().map(|k| -> openpgp::Packet {
617                        if k.fingerprint() == fp {
618                            k.role_into_primary().into()
619                        } else {
620                            k.role_into_subordinate().into()
621                        }
622                    }))
623                .map_err(sop_error)?;
624
625            result.push(key);
626        }
627
628        Ok(Keys {
629            sop: self.sqop,
630            keys: result,
631            source_name: None,
632        })
633    }
634}
635
636struct RevokeKey<'s> {
637    #[allow(dead_code)]
638    sqop: &'s SQOP<'s>,
639    key_password: Vec<openpgp::crypto::Password>,
640}
641
642impl<'s> RevokeKey<'s> {
643    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
644        Ok(Box::new(RevokeKey {
645            sqop,
646            key_password: vec![],
647        }))
648    }
649}
650
651impl<'s> sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for RevokeKey<'s> {
652    fn with_key_password(mut self: Box<Self>, password: Password)
653                         -> Result<Box<dyn sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
654        for p in password.variants() {
655            self.key_password.push(p.into());
656        }
657        Ok(self)
658    }
659
660    fn keys(self: Box<Self>, keys: &Keys) -> Result<Certs<'s>> {
661        let sop_error = |e| self.sqop.sop_error(e);
662
663        let mut results = vec![];
664        for key in &keys.keys {
665            // Get the primary signer.
666            let mut primary = match key.primary_key().key().parts_as_secret() {
667                Ok(p) => p.clone(),
668                Err(_) => return Err(Error::BadData),
669            };
670
671            // Maybe unlock the secret.
672            if primary.secret().is_encrypted() {
673                let mut unlocked = false;
674
675                for p in &self.key_password {
676                    if let Ok(k) = primary.clone().decrypt_secret(p) {
677                        primary = k;
678                        unlocked = true;
679                        break;
680                    }
681                }
682
683                if ! unlocked {
684                    return Err(Error::KeyIsProtected);
685                }
686            }
687            let mut signer = primary.into_keypair().map_err(sop_error)?;
688
689            // And revoke the cert.
690            let revocation = key.revoke(&mut signer,
691                                        ReasonForRevocation::Unspecified,
692                                        b"unspecified").map_err(sop_error)?;
693            results.push(key.clone().insert_packets(
694                std::iter::once(openpgp::Packet::from(revocation)))
695                         .map(|(cert, _changed)| cert)
696                         .map_err(sop_error)?
697                         .strip_secret_key_material());
698        }
699
700        Ok(Certs {
701            sop: self.sqop,
702            certs: results,
703            source_name: None,
704        })
705    }
706}
707
708struct ExtractCert<'s> {
709    #[allow(dead_code)]
710    sqop: &'s SQOP<'s>,
711}
712
713impl<'s> ExtractCert<'s> {
714    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ExtractCert<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
715        Ok(Box::new(ExtractCert {
716            sqop,
717        }))
718    }
719}
720
721impl<'s> sop::ops::ExtractCert<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for ExtractCert<'s> {
722    fn keys(self: Box<Self>, keys: &Keys) -> Result<Certs<'s>> {
723        Ok(Certs {
724            sop: self.sqop,
725            certs: keys.keys.iter()
726                .map(|c| c.clone().strip_secret_key_material())
727                .collect::<Vec<_>>(),
728            source_name: None,
729        })
730    }
731}
732
733struct MergeCerts<'s> {
734    #[allow(dead_code)]
735    sqop: &'s SQOP<'s>,
736    updates: BTreeMap<openpgp::Fingerprint, openpgp::Cert>,
737}
738
739impl<'s> MergeCerts<'s> {
740    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> + 's>> {
741        Ok(Box::new(MergeCerts {
742            sqop,
743            updates: Default::default(),
744        }))
745    }
746
747    fn merge_internal(&mut self, updates: &Certs) -> Result<()> {
748        let sop_error = |e| self.sqop.sop_error(e);
749
750        use std::collections::btree_map::Entry;
751
752        for cert in updates.certs.iter().cloned() {
753            match self.updates.entry(cert.fingerprint()) {
754                Entry::Occupied(e) => {
755                    let e = e.into_mut();
756                    *e = e.clone().merge_public(cert).map_err(sop_error)?;
757                },
758                Entry::Vacant(e) => {
759                    e.insert(cert);
760                },
761            }
762        }
763
764        Ok(())
765    }
766}
767
768impl<'s> sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> for MergeCerts<'s> {
769    fn merge_updates(mut self: Box<Self>, updates: &Certs)
770                     -> Result<Box<dyn sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> + 's>> {
771        self.merge_internal(updates)?;
772        Ok(self)
773    }
774
775    fn merge(mut self: Box<Self>, certs: &Certs) -> Result<Certs<'s>> {
776        let fps: BTreeSet<_> =
777            certs.certs.iter().map(openpgp::Cert::fingerprint).collect();
778        self.merge_internal(certs)?;
779
780        Ok(Certs {
781            sop: self.sqop,
782            certs: fps.iter()
783                .map(|fp| self.updates.get(fp).expect("have ingested certs").clone())
784                .collect(),
785            source_name: None,
786        })
787    }
788}
789
790struct CertifyUserID<'s> {
791    #[allow(dead_code)]
792    sqop: &'s SQOP<'s>,
793    userids: Vec<String>,
794    with_key_password: Vec<Password>,
795    no_require_self_sig: bool,
796    certifiers: Vec<openpgp::Cert>,
797}
798
799impl<'s> CertifyUserID<'s> {
800    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
801        Ok(Box::new(CertifyUserID {
802            sqop,
803            userids: Default::default(),
804            with_key_password: Default::default(),
805            no_require_self_sig: false,
806            certifiers: Default::default(),
807        }))
808    }
809}
810
811impl<'s> sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for CertifyUserID<'s> {
812    fn userid(mut self: Box<Self>, userid: String)
813              -> Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
814        self.userids.push(userid);
815        self
816    }
817
818    fn with_key_password(mut self: Box<Self>, password: Password)
819                         -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
820        self.with_key_password.push(password);
821        Ok(self)
822    }
823
824    fn no_require_self_sig(mut self: Box<Self>)
825                           -> Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
826        self.no_require_self_sig = true;
827        self
828    }
829
830    fn keys(mut self: Box<Self>, keys: &Keys)
831            -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
832        for key in &keys.keys {
833            self.certifiers.push(key.clone());
834        }
835        Ok(self)
836    }
837
838    fn certify(self: Box<Self>, certs: &Certs)-> Result<Certs<'s>> {
839        let sop_error = |e| self.sqop.sop_error(e);
840
841        if self.certifiers.is_empty() {
842            return Err(Error::MissingArg);
843        }
844
845        let mut certifiers = Vec::with_capacity(self.certifiers.len());
846        for cert in &self.certifiers {
847            let vcert =
848                cert.with_policy(self.sqop.policy, None)
849            // XXX: https://gitlab.com/dkg/openpgp-stateless-cli/-/issues/119
850                .map_err(|e| {
851                    sop_error(e);
852                    Error::KeyCannotSign
853                })?;
854
855            if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
856                // XXX: https://gitlab.com/dkg/openpgp-stateless-cli/-/issues/119
857                return Err(Error::KeyCannotSign);
858            }
859
860            let mut one = false;
861            for ka in vcert.keys()
862                .supported()
863                .secret()
864                .alive()
865                .revoked(false)
866                .for_certification()
867            {
868                let mut key = ka.key().clone();
869                if key.secret().is_encrypted() {
870                    for p in self.with_key_password.iter()
871                        .flat_map(|p| p.variants())
872                    {
873                        if key.secret_mut()
874                            .decrypt_in_place(ka.key(), &p.into()).is_ok()
875                        {
876                            break;
877                        }
878                    }
879                }
880                if ! key.secret().is_encrypted() {
881                    one = true;
882                    // Exactly one certification per supplied key.
883                    certifiers.push(key.into_keypair().map_err(sop_error)?);
884                    break;
885                }
886            }
887
888            if ! one {
889                return Err(Error::KeyIsProtected);
890            }
891        }
892
893        let mut outputs = Vec::new();
894        for cert in &certs.certs {
895            let mut acc = Vec::<openpgp::Packet>::new();
896
897            for new_userid in &self.userids {
898                if ! self.no_require_self_sig
899                    && ! cert.userids().any(|u| u.userid().value() == new_userid.as_bytes())
900                {
901                    // XXX: https://gitlab.com/dkg/openpgp-stateless-cli/-/issues/119
902                    return Err(Error::UnspecifiedFailure);
903                }
904
905                let uid = openpgp::packet::UserID::from(new_userid.as_str());
906                acc.push(uid.clone().into());
907                for certifier in &mut certifiers {
908                    let sig = uid.bind(certifier, cert,
909                                       SignatureBuilder::new(
910                                           SignatureType::PositiveCertification))
911                        .map_err(sop_error)?;
912                    acc.push(sig.into());
913                }
914            }
915
916            outputs.push(cert.clone().insert_packets(acc)
917                         .map_err(sop_error)?.0);
918        }
919
920        Ok(Certs {
921            sop: self.sqop,
922            certs: outputs,
923            source_name: None,
924        })
925    }
926}
927
928struct ValidateUserID<'s> {
929    #[allow(dead_code)]
930    sqop: &'s SQOP<'s>,
931    trust_roots: Vec<openpgp::Cert>,
932    target_certs: Vec<openpgp::Cert>,
933    validate_at: Option<SystemTime>,
934}
935
936impl<'s> ValidateUserID<'s> {
937    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
938        Ok(Box::new(ValidateUserID {
939            sqop,
940            trust_roots: Default::default(),
941            target_certs: Default::default(),
942            validate_at: Default::default(),
943        }))
944    }
945
946    fn authenticate(&self, userid: &str, email: bool) -> Result<()> {
947        let sop_error = |e| self.sqop.sop_error(e);
948
949        tracer!(self.sqop.debug, "ValidateUserID::authenticate");
950        use sequoia_wot::{FULLY_TRUSTED, Network};
951
952        t!("authenticating {} {:?}",
953           if email { "email" } else { "user ID" }, userid);
954
955        let roots: Vec<_> =
956            self.trust_roots.iter().map(openpgp::Cert::fingerprint).collect();
957        t!("using trust roots {:?}", roots);
958
959        let n = Network::from_cert_refs(
960            self.trust_roots.iter().chain(self.target_certs.iter()),
961            self.sqop.policy,
962            self.validate_at.clone(),
963            &roots[..])
964            .map_err(sop_error)?;
965
966        if ! email {
967            // Match on the user ID as is.
968            let uid = openpgp::packet::UserID::from(userid);
969
970            for cert in &self.target_certs {
971                t!("considering {}", cert.fingerprint());
972
973                let paths =
974                    n.authenticate(&uid, cert.fingerprint(), FULLY_TRUSTED);
975                t!("authenticate({:?}, {}) => {}",
976                   cert.fingerprint(), userid, paths.amount());
977
978                if paths.amount() < FULLY_TRUSTED {
979                    return Err(Error::CertUseridNoMatch);
980                }
981            }
982        } else {
983            // Match on the email addresses.
984            for cert in &self.target_certs {
985                t!("considering {}", cert.fingerprint());
986
987                let mut one = false;
988                for uid in cert.userids()
989                    .filter(|u| u.userid().email().ok().flatten()
990                            .map(|email| email == userid)
991                            .unwrap_or(false))
992                {
993                    let paths =
994                        n.authenticate(uid.userid(), cert.fingerprint(),
995                                       FULLY_TRUSTED);
996                    t!("authenticate({}, {:?}) => {}",
997                       cert.fingerprint(), userid, paths.amount());
998
999                    if paths.amount() >= FULLY_TRUSTED {
1000                        one = true;
1001                        break;
1002                    }
1003                }
1004
1005                if ! one {
1006                    return Err(Error::CertUseridNoMatch);
1007                }
1008            }
1009        }
1010
1011        Ok(())
1012    }
1013}
1014
1015impl<'s> sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> for ValidateUserID<'s> {
1016    fn trust_roots(mut self: Box<Self>, certs: &Certs)
1017            -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1018        for cert in &certs.certs {
1019            self.trust_roots.push(cert.clone());
1020        }
1021        Ok(self)
1022    }
1023
1024    fn target_certs(mut self: Box<Self>, certs: &Certs)
1025            -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1026        for cert in &certs.certs {
1027            self.target_certs.push(cert.clone());
1028        }
1029        Ok(self)
1030    }
1031
1032    fn validate_at(mut self: Box<Self>, at: SystemTime)
1033            -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1034        self.validate_at = Some(at);
1035        Ok(self)
1036    }
1037
1038    fn userid(self: Box<Self>, userid: &str) -> Result<()> {
1039        self.authenticate(userid, false)
1040    }
1041
1042    fn email(self: Box<Self>, address: &str) -> Result<()> {
1043        self.authenticate(address, true)
1044    }
1045}
1046
1047struct Sign<'s> {
1048    sqop: &'s SQOP<'s>,
1049    mode: SignAs,
1050    hash_algos: Vec<HashAlgorithm>,
1051    with_key_password: Vec<Password>,
1052    signers: Vec<openpgp::Cert>,
1053}
1054
1055impl<'s> Sign<'s> {
1056    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1057        Ok(Box::new(Self::unboxed(sqop)))
1058    }
1059
1060    fn unboxed(sqop: &'s SQOP) -> Sign<'s> {
1061        Sign {
1062            sqop,
1063            mode: Default::default(),
1064            hash_algos: [
1065                HashAlgorithm::SHA512,
1066                HashAlgorithm::SHA384,
1067                HashAlgorithm::SHA256,
1068                HashAlgorithm::SHA224,
1069            ].iter().copied().filter(|h| h.is_supported()).collect(),
1070            with_key_password: Default::default(),
1071            signers: Default::default(),
1072        }
1073    }
1074}
1075
1076impl Sign<'_> {
1077    fn add_signing_keys(&mut self, keys: &Keys) -> Result<()> {
1078        for key in &keys.keys {
1079            self.add_signing_cert(key)?;
1080        }
1081        Ok(())
1082    }
1083
1084    fn add_signing_cert(&mut self, cert: &Cert) -> Result<()> {
1085        let vcert =
1086            cert.with_policy(self.sqop.policy, None)
1087            .map_err(|e| {
1088                self.sqop.sop_error(e);
1089                Error::KeyCannotSign
1090            })?;
1091
1092        if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
1093            return Err(Error::KeyCannotSign);
1094        }
1095
1096        if let Some(p) = vcert.preferred_hash_algorithms() {
1097            self.hash_algos.retain(|a| p.contains(a));
1098        }
1099
1100        if vcert.keys()
1101            .supported()
1102            .secret()
1103            .alive()
1104            .revoked(false)
1105            .for_signing()
1106            .next().is_none()
1107        {
1108            return Err(Error::KeyCannotSign);
1109        }
1110
1111        self.signers.push(cert.clone());
1112        Ok(())
1113    }
1114
1115    /// Returns the set of signers.
1116    fn make_signers(&self) -> Result<Vec<openpgp::crypto::KeyPair>> {
1117        let sop_error = |e| self.sqop.sop_error(e);
1118
1119        let mut signers = Vec::with_capacity(self.signers.len());
1120        for cert in &self.signers {
1121            let vcert =
1122                cert.with_policy(self.sqop.policy, None)
1123                .map_err(|e| {
1124                    sop_error(e);
1125                    Error::KeyCannotSign
1126                })?;
1127
1128            let mut one = false;
1129            for skb in vcert.keys()
1130                .supported()
1131                .secret()
1132                .alive()
1133                .revoked(false)
1134                .for_signing()
1135            {
1136                let mut key = skb.key().clone();
1137
1138                if key.secret().is_encrypted() {
1139                    for p in self.with_key_password.iter()
1140                        .flat_map(|p| p.variants())
1141                    {
1142                        if key.secret_mut().decrypt_in_place(skb.key(), &p.into())
1143                            .is_ok()
1144                        {
1145                            break;
1146                        }
1147                    }
1148                }
1149                if ! key.secret().is_encrypted() {
1150                    one = true;
1151                    // Exactly one signature per supplied key.
1152                    signers.push(key.into_keypair().map_err(sop_error)?);
1153                    break;
1154                }
1155            }
1156
1157            if ! one {
1158                return Err(Error::KeyIsProtected);
1159            }
1160        }
1161
1162        Ok(signers)
1163    }
1164}
1165
1166impl<'s> sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> for Sign<'s> {
1167    fn mode(mut self: Box<Self>, mode: SignAs)
1168            -> Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's> {
1169        self.mode = mode;
1170        self
1171    }
1172
1173    fn keys(mut self: Box<Self>, keys: &Keys)
1174            -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1175        self.add_signing_keys(keys)?;
1176        Ok(self)
1177    }
1178
1179    fn with_key_password(mut self: Box<Self>, password: Password)
1180                         -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1181        self.with_key_password.push(password);
1182        Ok(self)
1183    }
1184
1185    fn data(self: Box<Self>, data: &mut (dyn io::Read + Send + Sync))
1186            -> Result<(sop::ops::Micalg, Sigs<'s>)>
1187    {
1188        let sop_error = |e| self.sqop.sop_error(e);
1189
1190        if self.signers.is_empty() {
1191            return Err(Error::MissingArg);
1192        }
1193
1194        let mut buf = vec![];
1195        let message = Message::new(&mut buf);
1196        let mut signers = self.make_signers()?;
1197        let mut signer = Signer::with_template(
1198            message,
1199            signers.pop().expect("at least one"),
1200            signature::SignatureBuilder::new(into_sig_type(self.mode)))
1201            .map_err(sop_error)?
1202            .hash_algo(
1203                self.hash_algos.get(0).cloned().unwrap_or_default()
1204            ).map_err(sop_error)?
1205            .detached();
1206        for s in signers {
1207            signer = signer.add_signer(s).map_err(sop_error)?;
1208        }
1209        let mut message = signer.build().map_err(sop_error)?;
1210        io::copy(data, &mut message)?;
1211        message.finalize().map_err(sop_error)?;
1212
1213        Ok((u8::from(HashAlgorithm::default()).into(),
1214            Sigs::from_bytes(self.sqop, &buf)?))
1215    }
1216}
1217
1218struct Verify<'s> {
1219    sqop: &'s SQOP<'s>,
1220    verbose: bool,
1221    not_before: Option<SystemTime>,
1222    not_after: Option<SystemTime>,
1223    certs: CertBag,
1224}
1225
1226impl<'s> Verify<'s> {
1227    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's>> {
1228        Ok(Box::new(Self::unboxed(sqop)))
1229    }
1230
1231    fn unboxed(sqop: &'s SQOP) -> Verify<'s>
1232    where
1233        's: 's,
1234    {
1235        Verify {
1236            sqop,
1237            verbose: Default::default(),
1238            not_before: Default::default(),
1239            not_after: Default::default(),
1240            certs: Default::default(),
1241        }
1242    }
1243}
1244
1245impl<'s> sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> for Verify<'s> {
1246    fn not_before(mut self: Box<Self>, t: SystemTime)
1247                  -> Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's> {
1248        self.not_before = Some(t);
1249        self
1250    }
1251
1252    fn not_after(mut self: Box<Self>, t: SystemTime)
1253                 -> Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's> {
1254        self.not_after = Some(t);
1255        self
1256    }
1257
1258    fn certs(mut self: Box<Self>, cert: &Certs)
1259             -> Result<Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's>> {
1260        self.certs.extend_from(cert);
1261        Ok(self)
1262    }
1263
1264    fn signatures<'sigs>(self: Box<Self>, signatures: &'sigs Sigs)
1265                         -> Result<Box<dyn sop::ops::VerifySignatures<'sigs> + 'sigs>>
1266    where
1267        's: 'sigs,
1268    {
1269        Ok(Box::new(VerifySignatures {
1270            verify: *self,
1271            signatures: signatures,
1272        }))
1273    }
1274}
1275
1276struct VerifySignatures<'s, 'sigs> {
1277    verify: Verify<'s>,
1278    signatures: &'sigs Sigs<'s>,
1279}
1280
1281impl sop::ops::VerifySignatures<'_> for VerifySignatures<'_, '_> {
1282    fn data(self: Box<Self>, data: &mut (dyn io::Read + Send + Sync))
1283            -> Result<Vec<sop::ops::Verification>> {
1284        let sop_error = |e| self.verify.sqop.sop_error(e);
1285
1286        if self.verify.certs.is_empty() {
1287            return Err(Error::MissingArg);
1288        }
1289
1290        let helper = VHelper::new(
1291            if self.verify.verbose {
1292                Box::new(io::stderr())
1293            } else {
1294                Box::new(io::sink())
1295            },
1296            1,
1297            self.verify.not_before,
1298            self.verify.not_after,
1299            self.verify.certs);
1300        let mut v =
1301            DetachedVerifierBuilder::from_bytes(&self.signatures.data)
1302            .map_err(sop_error)?
1303            .with_policy(self.verify.sqop.policy, None, helper)
1304            .map_err(sop_error)?;
1305        v.verify_reader(data).map_err(sop_error)?;
1306        Ok(v.into_helper().verifications)
1307    }
1308}
1309
1310struct Encrypt<'s> {
1311    no_armor: bool,
1312    sign: Sign<'s>,
1313    profile: &'static str,
1314    mode: EncryptAs,
1315    symmetric_algos: Vec<SymmetricAlgorithm>,
1316    aead_algos: Vec<(SymmetricAlgorithm, AEADAlgorithm)>,
1317    recipients: Vec<(Features, Key<key::PublicParts, key::UnspecifiedRole>)>,
1318    passwords: Vec<Password>,
1319}
1320
1321impl<'s> Encrypt<'s> {
1322    const PROFILE_RFC9580: &'static str = "rfc9580";
1323    const PROFILE_RFC4880: &'static str = "rfc4880";
1324    const PROFILES: &'static [(&'static str, &'static str)] = &[
1325        (Self::PROFILE_RFC9580, "use SEIPDv2"),
1326        (Self::PROFILE_RFC4880, "use SEIPDv1"),
1327    ];
1328
1329    fn normalize_profile(profile: &str) -> Result<&'static str> {
1330        match profile {
1331            Self::PROFILE_RFC9580 => Ok(Self::PROFILE_RFC9580),
1332            Self::PROFILE_RFC4880 => Ok(Self::PROFILE_RFC4880),
1333
1334            // The symbolic aliases.
1335            "default" => Ok(match openpgp::Profile::default() {
1336                openpgp::Profile::RFC4880 => Self::PROFILE_RFC4880,
1337                openpgp::Profile::RFC9580 => Self::PROFILE_RFC9580,
1338                _ => Self::PROFILE_RFC9580,
1339            }),
1340            "security" => Ok(Self::PROFILE_RFC9580),
1341            "performance" => Ok(Self::PROFILE_RFC9580),
1342            "compatibility" => Ok(Self::PROFILE_RFC4880),
1343
1344            _ => Err(Error::UnsupportedProfile),
1345        }
1346    }
1347
1348    const SYMMETRIC_ALGOS: &'static [SymmetricAlgorithm] = &[
1349        SymmetricAlgorithm::AES256,
1350        SymmetricAlgorithm::AES192,
1351        SymmetricAlgorithm::AES128,
1352        SymmetricAlgorithm::Camellia256,
1353        SymmetricAlgorithm::Camellia192,
1354        SymmetricAlgorithm::Camellia128,
1355        SymmetricAlgorithm::Blowfish,
1356        SymmetricAlgorithm::Twofish,
1357    ];
1358
1359    const AEAD_ALGOS: &'static [AEADAlgorithm] = &[
1360        AEADAlgorithm::OCB,
1361        AEADAlgorithm::GCM,
1362        AEADAlgorithm::EAX,
1363    ];
1364
1365    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1366        Ok(Box::new(Encrypt {
1367            no_armor: false,
1368            sign: Sign::unboxed(sqop),
1369            profile: Self::normalize_profile("default")?,
1370            mode: Default::default(),
1371            symmetric_algos: Self::SYMMETRIC_ALGOS.iter().copied().filter(|&a| {
1372                a.is_supported() && sqop.policy.symmetric_algorithm(a).is_ok()
1373            }).collect(),
1374            aead_algos: Self::SYMMETRIC_ALGOS.iter().copied().filter(|&a| {
1375                a.is_supported() && sqop.policy.symmetric_algorithm(a).is_ok()
1376            }).flat_map(|s| Self::AEAD_ALGOS.iter().copied().filter(|&a| {
1377                a.is_supported() && sqop.policy.aead_algorithm(a).is_ok()
1378            }).map(move |a| (s, a))).collect(),
1379            recipients: Default::default(),
1380            passwords: Default::default(),
1381        }))
1382    }
1383
1384    fn add_cert(mut self: Box<Self>, cert: &Cert)
1385                 -> Result<Box<Self>> {
1386        let vcert = cert.with_policy(self.sign.sqop.policy, None)
1387            .map_err(|e| {
1388                self.sign.sqop.sop_error(e);
1389                Error::CertCannotEncrypt
1390            })?;
1391
1392        if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
1393            return Err(Error::CertCannotEncrypt);
1394        }
1395
1396        // If the recipients has preferences, compute the
1397        // intersection with our list.
1398        if let Some(p) = vcert.preferred_hash_algorithms() {
1399            self.sign.hash_algos.retain(|a| p.contains(a));
1400        }
1401        if let Some(p) = vcert.preferred_symmetric_algorithms() {
1402            self.symmetric_algos.retain(|a| p.contains(a));
1403        }
1404        if let Some(p) = vcert.preferred_aead_ciphersuites() {
1405            self.aead_algos.retain(|a| p.contains(a));
1406        }
1407
1408        // Gracefully fall back to SEIPDv1.
1409        if ! vcert.features().map(|f| f.supports_seipdv2())
1410            .unwrap_or_else(|| vcert.primary_key().key().version() == 6)
1411        {
1412            self.profile = Self::PROFILE_RFC4880;
1413        }
1414
1415        let mut one = false;
1416        for vka in vcert.keys()
1417            .supported()
1418            .alive()
1419            .revoked(false)
1420            .for_storage_encryption()
1421            .for_transport_encryption()
1422        {
1423            self.recipients.push(
1424                (vka.valid_cert().features().unwrap_or_else(Features::empty),
1425                 vka.key().clone()));
1426            one = true;
1427        }
1428
1429        if one {
1430            Ok(self)
1431        } else {
1432            Err(Error::CertCannotEncrypt)
1433        }
1434    }
1435}
1436
1437impl<'s> sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for Encrypt<'s> {
1438    fn no_armor(mut self: Box<Self>) -> Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1439        self.no_armor = true;
1440        self
1441    }
1442
1443    fn list_profiles(&self) -> Vec<(String, String)> {
1444        list_profiles(Self::PROFILES, &Self::normalize_profile)
1445    }
1446
1447    fn profile(mut self: Box<Self>, profile: &str)
1448               -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1449        self.profile = Self::normalize_profile(profile)?;
1450        Ok(self)
1451    }
1452
1453    fn mode(mut self: Box<Self>, mode: EncryptAs) -> Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1454        self.sign.mode = mode.into();
1455        self.mode = mode;
1456        self
1457    }
1458
1459    fn sign_with_keys(mut self: Box<Self>,
1460                      keys: &Keys)
1461                      -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1462        self.sign.add_signing_keys(keys)?;
1463        Ok(self)
1464    }
1465
1466    fn with_key_password(mut self: Box<Self>, password: Password)
1467                         -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1468        self.sign.with_key_password.push(password);
1469        Ok(self)
1470    }
1471
1472    fn with_password(mut self: Box<Self>, password: Password)
1473                     -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1474        self.passwords.push(password);
1475        Ok(self)
1476    }
1477
1478    fn with_certs(mut self: Box<Self>, certs: &Certs)
1479                  -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1480        for cert in &certs.certs {
1481            self = self.add_cert(cert)?;
1482        }
1483        Ok(self)
1484    }
1485
1486    fn plaintext<'d>(self: Box<Self>,
1487                     plaintext: &'d mut (dyn io::Read + Send + Sync))
1488                     -> Result<Box<dyn sop::ops::Ready<Option<sop::SessionKey>> + 'd>>
1489    where
1490        's: 'd
1491    {
1492        Ok(Box::new(EncryptReady {
1493            encrypt: *self,
1494            plaintext,
1495        }))
1496    }
1497}
1498
1499struct EncryptReady<'s> {
1500    encrypt: Encrypt<'s>,
1501    plaintext: &'s mut (dyn io::Read + Send + Sync),
1502}
1503
1504impl<'s> sop::ops::Ready<Option<sop::SessionKey>> for EncryptReady<'s> {
1505    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1506                -> Result<Option<sop::SessionKey>>
1507    {
1508        let sop_error = |e| self.encrypt.sign.sqop.sop_error(e);
1509
1510        if self.encrypt.recipients.is_empty()
1511            && self.encrypt.passwords.is_empty()
1512        {
1513            return Err(Error::MissingArg);
1514        }
1515
1516        let mut message = Message::new(sink);
1517        if ! self.encrypt.no_armor {
1518            message = Armorer::new(message).build().map_err(sop_error)?;
1519        }
1520
1521        // XXX: Honor self.profile once we have more than one.
1522
1523        // Encrypt the message.
1524        let (cipher, aead_algo) = match self.encrypt.profile {
1525            Encrypt::PROFILE_RFC9580 => {
1526                let (c, a) = self.encrypt.aead_algos.get(0).cloned()
1527                    .unwrap_or(
1528                        // Fall back to the MTI algorithms.
1529                        (SymmetricAlgorithm::AES128, AEADAlgorithm::OCB));
1530                (c, Some(a))
1531            },
1532            Encrypt::PROFILE_RFC4880 => {
1533                (self.encrypt.symmetric_algos.get(0).cloned()
1534                 .unwrap_or_default(),
1535                 None)
1536            },
1537            _ => unreachable!("checked in Encrypt::profile"),
1538        };
1539
1540        let session_key =
1541            SessionKey::new(cipher.key_size().map_err(sop_error)?)
1542            .map_err(sop_error)?;
1543        let sop_session_key = sop::SessionKey::new(cipher, &session_key)?;
1544        let mut encryptor =
1545            Encryptor::with_session_key(message, cipher, session_key)
1546            .map_err(sop_error)?
1547            .add_recipients(
1548                self.encrypt.recipients.iter()
1549                    .map(|(f, k)| Recipient::new(f.clone(), k.key_handle(), k)))
1550            .add_passwords(
1551                self.encrypt.passwords.into_iter()
1552                    .map(|p| crypto::Password::from(p.normalized())))
1553                .symmetric_algo(cipher);
1554
1555        if let Some(a) = aead_algo {
1556            encryptor = encryptor.aead_algo(a);
1557        }
1558
1559        let mut message = encryptor
1560            .build().map_err(sop_error)?;
1561
1562        // Enable padding if possible.
1563        message = Padder::new(message).build().map_err(sop_error)?;
1564
1565        // Maybe sign the message.
1566        let mut signers = self.encrypt.sign.make_signers()?;
1567        if let Some(first) = signers.pop() {
1568            let mut signer = Signer::with_template(
1569                message, first,
1570                signature::SignatureBuilder::new(into_sig_type(self.encrypt.sign.mode)))
1571                .map_err(sop_error)?
1572                .hash_algo(
1573                    self.encrypt.sign.hash_algos.get(0).cloned().unwrap_or_default())
1574                .map_err(sop_error)?;
1575            for s in signers {
1576                signer = signer.add_signer(s).map_err(sop_error)?;
1577            }
1578            message = signer.build().map_err(sop_error)?;
1579        }
1580
1581        // Literal wrapping.
1582        let mut message = LiteralWriter::new(message)
1583                .build().map_err(sop_error)?;
1584        io::copy(self.plaintext, &mut message)?;
1585        message.finalize().map_err(sop_error)?;
1586        Ok(Some(sop_session_key))
1587    }
1588}
1589
1590struct Decrypt<'s> {
1591    verify: Verify<'s>,
1592    session_keys: Vec<sop::SessionKey>,
1593    passwords: Vec<Password>,
1594    keys: Vec<Cert>,
1595    with_key_password: Vec<Password>,
1596}
1597
1598impl<'s> Decrypt<'s> {
1599    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1600        Ok(Box::new(Decrypt {
1601            verify: Verify::unboxed(sqop),
1602            session_keys: Default::default(),
1603            passwords: Default::default(),
1604            keys: Default::default(),
1605            with_key_password: Default::default(),
1606        }))
1607    }
1608}
1609
1610impl<'s> sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for Decrypt<'s> {
1611    fn verify_not_before(mut self: Box<Self>, t: SystemTime)
1612                         -> Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1613        self.verify.not_before = Some(t);
1614        self
1615    }
1616
1617    fn verify_not_after(mut self: Box<Self>, t: SystemTime)
1618                        -> Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1619        self.verify.not_after = Some(t);
1620        self
1621    }
1622
1623    fn verify_with_certs(mut self: Box<Self>,
1624                         certs: &Certs)
1625                         -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1626        self.verify.certs.extend_from(certs);
1627        Ok(self)
1628    }
1629
1630    fn with_session_key(mut self: Box<Self>, sk: sop::SessionKey)
1631                        -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1632        self.session_keys.push(sk);
1633        Ok(self)
1634    }
1635
1636    fn with_password(mut self: Box<Self>, password: Password)
1637                     -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1638        self.passwords.push(password);
1639        Ok(self)
1640    }
1641
1642    fn with_keys(mut self: Box<Self>, keys: &Keys)
1643                 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1644        for key in &keys.keys {
1645            self.keys.push(key.clone());
1646        }
1647        Ok(self)
1648    }
1649
1650    fn with_key_password(mut self: Box<Self>, password: Password)
1651                         -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1652        self.with_key_password.push(password);
1653        Ok(self)
1654    }
1655
1656    fn ciphertext<'d>(self: Box<Self>,
1657                      ciphertext: &'d mut (dyn io::Read + Send + Sync))
1658                      -> Result<Box<dyn sop::ops::Ready<(Option<sop::SessionKey>,
1659                                                    Vec<sop::ops::Verification>)> + 'd>>
1660    where
1661        's: 'd
1662    {
1663        Ok(Box::new(DecryptReady {
1664            decrypt: *self,
1665            ciphertext,
1666        }))
1667    }
1668}
1669
1670struct DecryptReady<'s> {
1671    decrypt: Decrypt<'s>,
1672    ciphertext: &'s mut (dyn io::Read + Send + Sync),
1673}
1674
1675impl<'s> sop::ops::Ready<(Option<sop::SessionKey>, Vec<sop::ops::Verification>)>
1676    for DecryptReady<'s>
1677{
1678    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1679                -> Result<(Option<sop::SessionKey>, Vec<sop::ops::Verification>)> {
1680
1681        let sop_error = |e| self.decrypt.verify.sqop.sop_error(e);
1682
1683        let vhelper = VHelper::new(
1684            if self.decrypt.verify.verbose {
1685                Box::new(io::stderr())
1686            } else {
1687                Box::new(io::sink())
1688            },
1689            0,
1690            self.decrypt.verify.not_before,
1691            self.decrypt.verify.not_after,
1692            self.decrypt.verify.certs);
1693        let helper = Helper::new(self.decrypt.verify.sqop.policy,
1694                                 vhelper,
1695                                 self.decrypt.session_keys,
1696                                 self.decrypt.passwords,
1697                                 self.decrypt.with_key_password,
1698                                 self.decrypt.keys);
1699        let mut d = DecryptorBuilder::from_reader(self.ciphertext)
1700            .map_err(sop_error)?
1701            .with_policy(self.decrypt.verify.sqop.policy, None, helper)
1702            .map_err(sop_error)?;
1703
1704        io::copy(&mut d, sink)?;
1705
1706        let helper = d.into_helper();
1707        Ok((helper.session_key, helper.vhelper.verifications))
1708    }
1709}
1710
1711struct Armor<'s> {
1712    sqop: &'s SQOP<'s>,
1713    label: ArmorLabel,
1714}
1715
1716impl<'s> Armor<'s> {
1717    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Armor<'s> + 's>> {
1718        Ok(Box::new(Armor {
1719            sqop,
1720            label: Default::default(),
1721        }))
1722    }
1723
1724    /// Parse the packet stream to guess the label and profile.
1725    ///
1726    /// We make no effort to verify the packet structure.
1727    fn dpi(&self, mut source: Box<dyn BufferedReader<Cookie> + 's>)
1728           -> Result<(Box<dyn BufferedReader<Cookie> + 's>,
1729                      Option<armor::Kind>,
1730                      openpgp::Profile)>
1731    {
1732        let sop_error = |e| self.sqop.sop_error(e);
1733
1734        // Our guess at what kind of data we're looking at.
1735        let mut kind = None;
1736
1737        // Our guess for the OpenPGP profile.
1738        let mut profile = None;
1739
1740        // What kind of signatures we saw.
1741        let mut saw_sig_v4 = false;
1742        let mut saw_sig_v6 = false;
1743
1744        // What kind of keys we saw.
1745        let mut saw_key_v4 = false;
1746        let mut saw_key_v6 = false;
1747
1748        source = Dup::with_cookie(source, Default::default()).into_boxed();
1749        {
1750            let mut ppr = PacketParser::from_buffered_reader(&mut source)
1751                .map_err(sop_error)?;
1752
1753            while let PacketParserResult::Some(pp) = ppr {
1754                if kind.is_none() {
1755                    // Autodetect using the first packet.
1756                    kind = Some(match &pp.packet {
1757                        Packet::Signature(_) =>
1758                            armor::Kind::Signature,
1759                        Packet::SecretKey(_) =>
1760                            armor::Kind::SecretKey,
1761                        Packet::PublicKey(_) =>
1762                            armor::Kind::PublicKey,
1763                        Packet::PKESK(_) | Packet::SKESK(_)
1764                            | Packet::OnePassSig(_) =>
1765                            armor::Kind::Message,
1766                        _ => return Err(Error::BadData),
1767                    });
1768                }
1769
1770                // Inspect the packet versions, and either call the
1771                // profile now, or track which packet versions we
1772                // encounter.  We do not recurse into containers.
1773                match &pp.packet {
1774                    Packet::SEIP(s) => {
1775                        match s.version() {
1776                            1 =>
1777                                profile = Some(openpgp::Profile::RFC4880),
1778
1779                            2 | _ =>
1780                                profile = Some(openpgp::Profile::RFC9580),
1781                        }
1782
1783                        // We've seen enough.
1784                        break;
1785                    },
1786
1787                    Packet::Literal(_) => {
1788                        // Either we've seen enough, or we cannot possibly
1789                        // learn anything more from a well formed message.
1790                        break;
1791                    },
1792
1793                    Packet::Signature(s) => {
1794                        saw_sig_v4 |= s.version() == 3;
1795                        saw_sig_v4 |= s.version() == 4;
1796                        saw_sig_v6 |= s.version() == 6;
1797                    },
1798                    Packet::OnePassSig(s) => {
1799                        saw_sig_v4 |= s.version() == 3;
1800                        saw_sig_v6 |= s.version() == 6;
1801                    },
1802
1803                    Packet::SecretKey(k) => {
1804                        saw_key_v4 |= k.version() == 4;
1805                        saw_key_v6 |= k.version() == 6;
1806                    },
1807                    Packet::PublicKey(k) => {
1808                        saw_key_v4 |= k.version() == 4;
1809                        saw_key_v6 |= k.version() == 6;
1810                    },
1811
1812                    _ => (),
1813                }
1814
1815                ppr = pp.next().map_err(sop_error)?.1;
1816            }
1817        }
1818
1819        // Pop off the Dup reader.
1820        //drop(ppr);
1821        source = source.into_inner()
1822            .expect("the Dup to be popped off");
1823
1824        // Guess the profile, if not yet called.
1825        let profile = match profile {
1826            Some(p) => p,
1827            None => match (saw_sig_v4, saw_sig_v6, saw_key_v4, saw_key_v6) {
1828                (false, false, false, false) => openpgp::Profile::default(),
1829                (false,  true, false, false) => openpgp::Profile::RFC9580,
1830                ( true, false, false, false) => openpgp::Profile::RFC4880,
1831                ( true,  true, false, false) => openpgp::Profile::RFC4880,
1832                (    _,     _, false,  true) => openpgp::Profile::RFC9580,
1833                (    _,     _,  true, false) => openpgp::Profile::RFC4880,
1834                (    _,     _,  true,  true) => openpgp::Profile::RFC4880,
1835            },
1836        };
1837
1838        Ok((source, kind, profile))
1839    }
1840}
1841
1842impl<'s> sop::ops::Armor<'s> for Armor<'s> {
1843    fn label(mut self: Box<Self>, label: ArmorLabel)
1844             -> Box<dyn sop::ops::Armor<'s> + 's> {
1845        self.label = label;
1846        self
1847    }
1848
1849    fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1850                -> Result<Box<dyn sop::ops::Ready + 'd>>
1851    where
1852        's: 'd
1853    {
1854        Ok(Box::new(ArmorReady {
1855            armor: *self,
1856            data,
1857        }))
1858    }
1859}
1860
1861struct ArmorReady<'s> {
1862    armor: Armor<'s>,
1863    data: &'s mut (dyn io::Read + Send + Sync),
1864}
1865
1866impl<'s> sop::ops::Ready for ArmorReady<'s> {
1867    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1868                -> Result<()> {
1869        let _ = self.armor.sqop;
1870
1871        let mut source =
1872            Generic::with_cookie(self.data, None, Cookie::default())
1873            .into_boxed();
1874
1875        // Peek at the data to see if it is already armored.
1876        let armored =
1877            source.data(1)?.get(0).map(|b| b & 0x80 == 0).unwrap_or(false);
1878
1879        // If so, dearmor, and extract the headers.
1880        let mut headers: Vec<(String, String)> = vec![];
1881        if armored {
1882            let mut r = armor::Reader::from_buffered_reader(
1883                source, armor::ReaderMode::Tolerant(None))?;
1884            headers = r.headers()?.iter().cloned().collect();
1885            source = r.into_boxed();
1886        }
1887
1888        // Parse the packet stream to guess the label and profile.
1889        let (source_, guess, profile) = self.armor.dpi(source)?;
1890        source = source_;
1891
1892        let kind = match self.armor.label {
1893            ArmorLabel::Auto => guess.ok_or(Error::BadData)?,
1894            ArmorLabel::Sig => armor::Kind::Signature,
1895            ArmorLabel::Key => armor::Kind::SecretKey,
1896            ArmorLabel::Cert => armor::Kind::PublicKey,
1897            ArmorLabel::Message => armor::Kind::Message,
1898        };
1899
1900        let mut sink = armor::Writer::with_headers(sink, kind, headers)?;
1901        sink.set_profile(profile)?;
1902        source.copy(&mut sink)?;
1903        sink.finalize()?;
1904        Ok(())
1905    }
1906}
1907
1908struct Dearmor<'s> {
1909    sqop: &'s SQOP<'s>,
1910}
1911
1912impl<'s> Dearmor<'s> {
1913    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Dearmor<'s> + 's>> {
1914        Ok(Box::new(Dearmor {
1915            sqop,
1916        }))
1917    }
1918}
1919
1920impl<'s> sop::ops::Dearmor<'s> for Dearmor<'s> {
1921    fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1922                -> Result<Box<dyn sop::ops::Ready + 'd>>
1923    where
1924        's: 'd
1925    {
1926        Ok(Box::new(DearmorReady {
1927            dearmor: *self,
1928            data,
1929        }))
1930    }
1931}
1932
1933struct DearmorReady<'s> {
1934    dearmor: Dearmor<'s>,
1935    data: &'s mut (dyn io::Read + Send + Sync),
1936}
1937
1938impl sop::ops::Ready for DearmorReady<'_> {
1939    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1940                -> Result<()> {
1941        let _ = self.dearmor.sqop;
1942
1943        // Peek at the data to see if it is really armored.  We make
1944        // no effort to verify the packet structure.
1945        let mut source =
1946            Generic::with_cookie(self.data, None, Cookie::default())
1947            .into_boxed();
1948        let armored =
1949            source.data(1)?.get(0).map(|b| b & 0x80 == 0).unwrap_or(false);
1950
1951        if armored {
1952            let mut r = armor::Reader::from_buffered_reader(source, None)?;
1953            r.copy(sink)?;
1954        } else {
1955            source.copy(sink)?;
1956        }
1957        Ok(())
1958    }
1959}
1960
1961struct InlineDetach<'s> {
1962    sqop: &'s SQOP<'s>,
1963    no_armor: bool,
1964}
1965
1966impl<'s> InlineDetach<'s> {
1967    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineDetach<'s, Sigs<'s>> + 's>> {
1968        Ok(Box::new(InlineDetach {
1969            sqop,
1970            no_armor: Default::default(),
1971        }))
1972    }
1973}
1974
1975impl<'s> sop::ops::InlineDetach<'s, Sigs<'s>> for InlineDetach<'s> {
1976    fn message<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1977        -> Result<Box<dyn sop::ops::Ready<Sigs<'s>> + 'd>>
1978    where
1979        's: 'd
1980    {
1981        Ok(Box::new(InlineDetachReady {
1982            inline_detach: *self,
1983            data,
1984        }))
1985    }
1986}
1987
1988struct InlineDetachReady<'s, 'd> {
1989    inline_detach: InlineDetach<'s>,
1990    data: &'d mut (dyn io::Read + Send + Sync),
1991}
1992
1993impl<'s> sop::ops::Ready<Sigs<'s>> for InlineDetachReady<'s, '_> {
1994    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1995                -> Result<Sigs<'s>> {
1996        let sop_error = |e| self.inline_detach.sqop.sop_error(e);
1997
1998        let _ = self.inline_detach.sqop;
1999
2000        let np = unsafe { NullPolicy::new() };
2001
2002        /// A nop-verification-helper to extract message and
2003        /// signatures.
2004        #[derive(Default)]
2005        struct NullHelper {
2006            sigs: Vec<Packet>,
2007        }
2008
2009        impl VerificationHelper for NullHelper {
2010            fn get_certs(&mut self, _: &[openpgp::KeyHandle])
2011                         -> openpgp::Result<Vec<Cert>> {
2012                Ok(Default::default())
2013            }
2014
2015            fn check(&mut self, structure: MessageStructure)
2016                     -> openpgp::Result<()> {
2017                for layer in structure {
2018                    match layer {
2019                        MessageLayer::SignatureGroup { results } => {
2020                            for result in results {
2021                                match result
2022                                    .expect_err("no certs given")
2023                                {
2024                                    VerificationError::MalformedSignature {
2025                                        sig, ..
2026                                    } =>
2027                                        self.sigs.push(sig.clone().into()),
2028                                    VerificationError::MissingKey {
2029                                        sig, ..
2030                                    } =>
2031                                        self.sigs.push(sig.clone().into()),
2032                                    _ => unreachable!("no certs given"),
2033                                }
2034                            }
2035                        },
2036                        _ => (),
2037                    }
2038                }
2039
2040                Ok(())
2041            }
2042        }
2043
2044        let mut verifier = VerifierBuilder::from_reader(self.data)
2045            .map_err(sop_error)?
2046            .with_policy(&np, None, NullHelper::default())
2047            .map_err(sop_error)?;
2048
2049        io::copy(&mut verifier, sink)?;
2050
2051        // Now get the signatures.
2052        let mut signatures = Vec::new();
2053        let mut signature_sink = Message::new(&mut signatures);
2054        if ! self.inline_detach.no_armor {
2055            signature_sink = Armorer::new(signature_sink)
2056                .kind(armor::Kind::Signature)
2057                .build().map_err(sop_error)?;
2058        }
2059
2060        for sig in verifier.into_helper().sigs {
2061            sig.serialize(&mut signature_sink).map_err(sop_error)?;
2062        }
2063        signature_sink.finalize().map_err(sop_error)?;
2064
2065        Ok(Sigs {
2066            sop: self.inline_detach.sqop,
2067            data: signatures,
2068            source_name: None,
2069        })
2070    }
2071}
2072
2073struct InlineVerify<'s> {
2074    sqop: &'s SQOP<'s>,
2075    verbose: bool,
2076    not_before: Option<SystemTime>,
2077    not_after: Option<SystemTime>,
2078    certs: CertBag,
2079}
2080
2081impl<'s> InlineVerify<'s> {
2082    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's>> {
2083        Ok(Box::new(InlineVerify {
2084            sqop,
2085            verbose: Default::default(),
2086            not_before: Default::default(),
2087            not_after: Default::default(),
2088            certs: Default::default(),
2089        }))
2090    }
2091}
2092
2093impl<'s> sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> for InlineVerify<'s> {
2094    fn not_before(mut self: Box<Self>, t: SystemTime)
2095                  -> Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's> {
2096        self.not_before = Some(t);
2097        self
2098    }
2099
2100    fn not_after(mut self: Box<Self>, t: SystemTime)
2101                 -> Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's> {
2102        self.not_after = Some(t);
2103        self
2104    }
2105
2106    fn certs(mut self: Box<Self>, certs: &Certs)
2107             -> Result<Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's>> {
2108        self.certs.extend_from(certs);
2109        Ok(self)
2110    }
2111
2112    fn message<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
2113        -> Result<Box<dyn sop::ops::Ready<Vec<Verification>> + 'd>>
2114    where
2115        's: 'd
2116    {
2117        Ok(Box::new(InlineVerifyReady {
2118            inline_verify: *self,
2119            data,
2120        }))
2121    }
2122}
2123
2124struct InlineVerifyReady<'s> {
2125    inline_verify: InlineVerify<'s>,
2126    data: &'s mut (dyn io::Read + Send + Sync),
2127}
2128
2129impl<'s> sop::ops::Ready<Vec<Verification>> for InlineVerifyReady<'_> {
2130    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
2131                -> Result<Vec<Verification>> {
2132        let sop_error = |e| self.inline_verify.sqop.sop_error(e);
2133
2134        let helper = VHelper::new(
2135            if self.inline_verify.verbose {
2136                Box::new(io::stderr())
2137            } else {
2138                Box::new(io::sink())
2139            },
2140            1,
2141            self.inline_verify.not_before,
2142            self.inline_verify.not_after,
2143            self.inline_verify.certs);
2144
2145        let mut verifier = VerifierBuilder::from_reader(self.data)
2146            .map_err(sop_error)?
2147            .with_policy(self.inline_verify.sqop.policy, None, helper)
2148            .map_err(sop_error)?;
2149
2150        io::copy(&mut verifier, sink)?;
2151
2152        Ok(verifier.into_helper().verifications)
2153    }
2154}
2155
2156struct InlineSign<'s> {
2157    no_armor: bool,
2158    sign: Sign<'s>,
2159    mode: InlineSignAs,
2160}
2161
2162impl<'s> InlineSign<'s> {
2163    fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2164        Ok(Box::new(InlineSign {
2165            no_armor: false,
2166            sign: Sign::unboxed(sqop),
2167            mode: Default::default(),
2168        }))
2169    }
2170}
2171
2172impl<'s> sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> for InlineSign<'s> {
2173    fn no_armor(mut self: Box<Self>) -> Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's> {
2174        self.no_armor = true;
2175        self
2176    }
2177
2178    fn mode(mut self: Box<Self>, mode: InlineSignAs) -> Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's> {
2179        self.mode = mode;
2180        self
2181    }
2182
2183    fn keys(mut self: Box<Self>, keys: &Keys)
2184           -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2185        self.sign.add_signing_keys(keys)?;
2186        Ok(self)
2187    }
2188
2189    fn with_key_password(mut self: Box<Self>, password: Password)
2190                         -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2191        self.sign.with_key_password.push(password);
2192        Ok(self)
2193    }
2194
2195    fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
2196        -> Result<Box<dyn sop::ops::Ready + 'd>>
2197    where
2198        's: 'd
2199    {
2200        if self.sign.signers.is_empty() {
2201            return Err(Error::MissingArg);
2202        }
2203
2204        if self.no_armor && matches!(self.mode, InlineSignAs::ClearSigned)
2205        {
2206            return Err(Error::IncompatibleOptions);
2207        }
2208
2209        Ok(Box::new(InlineSignReady {
2210            inline_sign: *self,
2211            data,
2212        }))
2213    }
2214}
2215
2216struct InlineSignReady<'s> {
2217    inline_sign: InlineSign<'s>,
2218    data: &'s mut (dyn io::Read + Send + Sync),
2219}
2220
2221impl<'s> sop::ops::Ready for InlineSignReady<'s> {
2222    fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
2223                -> Result<()>
2224    {
2225        let sop_error = |e| self.inline_sign.sign.sqop.sop_error(e);
2226
2227        let mut message = Message::new(sink);
2228        if ! (self.inline_sign.no_armor
2229              || matches!(self.inline_sign.mode, InlineSignAs::ClearSigned))
2230        {
2231            message =
2232                Armorer::new(message).build().map_err(sop_error)?;
2233        }
2234
2235        let mut signers = self.inline_sign.sign.make_signers()?;
2236        let mut signer = Signer::with_template(
2237            message,
2238            signers.pop().expect("at least one"),
2239            signature::SignatureBuilder::new(
2240                into_isig_type(self.inline_sign.mode)))
2241            .map_err(sop_error)?
2242            .hash_algo(
2243                self.inline_sign.sign.hash_algos.get(0).cloned()
2244                    .unwrap_or_default()).map_err(sop_error)?;
2245
2246        for s in signers {
2247            signer = signer.add_signer(s).map_err(sop_error)?;
2248        }
2249
2250        if matches!(self.inline_sign.mode, InlineSignAs::ClearSigned) {
2251            signer = signer.cleartext();
2252        }
2253
2254        let mut message = signer.build().map_err(sop_error)?;
2255
2256        if ! matches!(self.inline_sign.mode, InlineSignAs::ClearSigned) {
2257            message = LiteralWriter::new(message).build().map_err(sop_error)?;
2258        }
2259
2260        io::copy(self.data, &mut message)?;
2261        message.finalize().map_err(sop_error)?;
2262        Ok(())
2263    }
2264}
2265
2266/// Keeps track of certs and their origin.
2267#[derive(Default)]
2268struct CertBag {
2269    certs: BTreeMap<openpgp::Fingerprint, (Cert, Vec<String>)>,
2270}
2271
2272impl CertBag {
2273    fn is_empty(&self) -> bool {
2274        self.certs.is_empty()
2275    }
2276
2277    fn insert(&mut self, cert: Cert, source_name: Option<&str>) {
2278        use std::collections::btree_map::Entry;
2279        match self.certs.entry(cert.fingerprint()) {
2280            Entry::Occupied(mut e) => {
2281                let e = e.get_mut();
2282                e.0 = e.0.clone().merge_public(cert)
2283                    .expect("merging certs with the same fipr is infallible");
2284                if let Some(n) = source_name {
2285                    e.1.push(n.into());
2286                }
2287            },
2288            Entry::Vacant(e) => {
2289                e.insert((cert,
2290                          if let Some(n) = source_name {
2291                              vec![n.into()]
2292                          } else {
2293                              vec![]
2294                          }));
2295            },
2296        }
2297    }
2298
2299    fn extend_from(&mut self, certs: &Certs) {
2300        for cert in &certs.certs {
2301            self.insert(cert.clone(), certs.source_name());
2302        }
2303    }
2304}
2305
2306struct VHelper {
2307    verbose_out: Box<dyn io::Write>,
2308    verifications: Vec<Verification>,
2309    not_before: Option<SystemTime>,
2310    not_after: Option<SystemTime>,
2311
2312    good: usize,
2313    total: usize,
2314    threshold: usize,
2315
2316    keyring: CertBag,
2317}
2318
2319impl VHelper {
2320    fn new(verbose_out: Box<dyn io::Write>,
2321           threshold: usize,
2322           not_before: Option<SystemTime>,
2323           not_after: Option<SystemTime>,
2324           keyring: CertBag)
2325           -> Self
2326    {
2327        assert!(threshold <= 1);
2328        VHelper {
2329            verbose_out,
2330            verifications: Default::default(),
2331            not_before,
2332            not_after,
2333            good: 0,
2334            total: 0,
2335            threshold,
2336            keyring,
2337        }
2338    }
2339}
2340
2341impl VerificationHelper for VHelper {
2342    fn get_certs(&mut self, _: &[openpgp::KeyHandle])
2343                 -> openpgp::Result<Vec<Cert>> {
2344        Ok(self.keyring.certs.values()
2345           .map(|(cert, _)| cert.clone())
2346           .collect())
2347    }
2348
2349    fn check(&mut self, structure: MessageStructure) -> openpgp::Result<()> {
2350        use self::VerificationError::*;
2351
2352        for layer in structure.into_iter() {
2353            match layer {
2354                MessageLayer::SignatureGroup { results } =>
2355                    for result in results {
2356                        self.total += 1;
2357                        match result {
2358                            Ok(GoodChecksum { sig, ka, .. }) => {
2359                                let t = match sig.signature_creation_time() {
2360                                    Some(t) => t,
2361                                    None => {
2362                                        writeln!(self.verbose_out,
2363                                                 "Malformed signature:")?;
2364                                        print_error_chain(&mut self.verbose_out, &anyhow::anyhow!(
2365                                            "no signature creation time"))?;
2366                                        continue;
2367                                    },
2368                                };
2369
2370                                if let Some(not_before) = self.not_before {
2371                                    if t < not_before {
2372                                        writeln!(self.verbose_out,
2373                                            "Signature by {:X} was created before \
2374                                             the --not-before date.",
2375                                            ka.key().fingerprint())?;
2376                                        continue;
2377                                    }
2378                                }
2379
2380                                if let Some(not_after) = self.not_after {
2381                                    if t > not_after {
2382                                        writeln!(self.verbose_out,
2383                                            "Signature by {:X} was created after \
2384                                             the --not-after date.",
2385                                            ka.key().fingerprint())?;
2386                                        continue;
2387                                    }
2388                                }
2389                                let mut v = Verification::new(
2390                                    t,
2391                                    ka.key().fingerprint(),
2392                                    ka.cert().fingerprint(),
2393                                    match sig.typ() {
2394                                        SignatureType::Text =>
2395                                            SignatureMode::Text,
2396                                        _ => SignatureMode::Binary,
2397                                    },
2398                                    None)?;
2399
2400                                for n in self.keyring.certs.get(&ka.cert().fingerprint())
2401                                    .map(|(_, source_names)| source_names)
2402                                    .unwrap_or(&vec![])
2403                                {
2404                                    v.add_signer(n);
2405                                }
2406
2407                                self.verifications.push(v);
2408                            },
2409                            Err(MalformedSignature { error, .. }) => {
2410                                writeln!(self.verbose_out,
2411                                         "Signature is malformed:")?;
2412                                print_error_chain(&mut self.verbose_out, &error)?;
2413                            },
2414                            Err(MissingKey { sig, .. }) => {
2415                                let issuers = sig.get_issuers();
2416                                writeln!(self.verbose_out,
2417                                         "Missing key {:X}, which is needed to \
2418                                           verify signature.",
2419                                          issuers.first().unwrap())?;
2420                            },
2421                            Err(UnboundKey { cert, error, .. }) => {
2422                                writeln!(self.verbose_out,
2423                                         "Signing key on {:X} is not bound:",
2424                                          cert.fingerprint())?;
2425                                print_error_chain(&mut self.verbose_out, &error)?;
2426                            },
2427                            Err(BadKey { ka, error, .. }) => {
2428                                writeln!(self.verbose_out,
2429                                         "Signing key on {:X} is bad:",
2430                                          ka.cert().fingerprint())?;
2431                                print_error_chain(&mut self.verbose_out, &error)?;
2432                            },
2433                            Err(BadSignature { error, .. }) => {
2434                                writeln!(self.verbose_out,
2435                                         "Verifying signature:")?;
2436                                print_error_chain(&mut self.verbose_out, &error)?;
2437                            },
2438                            Err(UnknownSignature { sig, .. }) => {
2439                                writeln!(self.verbose_out,
2440                                         "Verifying signature:")?;
2441                                print_error_chain(&mut self.verbose_out, sig.error())?;
2442                            },
2443                            Err(error) => {
2444                                writeln!(self.verbose_out,
2445                                         "Verifying signature: {}", error)?;
2446                            },
2447                        }
2448                    }
2449                MessageLayer::Compression { .. } => (),
2450                MessageLayer::Encryption { .. } => (),
2451            }
2452        }
2453
2454        self.good = self.verifications.len();
2455        if self.good >= self.threshold {
2456            Ok(())
2457        } else {
2458            Err(Error::NoSignature.into())
2459        }
2460    }
2461}
2462
2463struct Helper {
2464    vhelper: VHelper,
2465    session_keys: Vec<sop::SessionKey>,
2466    passwords: Vec<crypto::Password>,
2467    secret_keys:
2468        HashMap<KeyID, Key<key::SecretParts, key::UnspecifiedRole>>,
2469    with_key_password: Vec<Password>,
2470    identities: HashMap<KeyID, Cert>,
2471    session_key: Option<sop::SessionKey>,
2472}
2473
2474impl Helper {
2475    fn new(policy: &dyn Policy,
2476           vhelper: VHelper,
2477           session_keys: Vec<sop::SessionKey>,
2478           passwords: Vec<Password>,
2479           with_key_password: Vec<Password>,
2480           secrets: Vec<Cert>) -> Self
2481    {
2482        let mut secret_keys = HashMap::new();
2483        let mut identities: HashMap<KeyID, Cert> = HashMap::new();
2484        for tsk in secrets {
2485            for ka in tsk.keys().secret()
2486                .with_policy(policy, None)
2487                .supported()
2488                .for_transport_encryption().for_storage_encryption()
2489            {
2490                let id: KeyID = ka.key().fingerprint().into();
2491                secret_keys.insert(id.clone(), ka.key().clone().into());
2492                identities.insert(id.clone(), tsk.clone().strip_secret_key_material());
2493            }
2494        }
2495
2496        Helper {
2497            vhelper,
2498            session_keys: session_keys.into_iter().map(Into::into).collect(),
2499            passwords: passwords.into_iter()
2500                .flat_map(|p| p.variants().map(crypto::Password::from)
2501                          .collect::<Vec<_>>()).collect(),
2502            secret_keys,
2503            with_key_password,
2504            identities,
2505            session_key: None,
2506        }
2507    }
2508
2509    /// Tries to decrypt the given PKESK packet with `keypair` and try
2510    /// to decrypt the packet parser using `decrypt`.
2511    fn try_decrypt(&self, pkesk: &PKESK,
2512                   algo_hint: Option<SymmetricAlgorithm>,
2513                   keypair: &mut dyn crypto::Decryptor,
2514                   decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
2515                   -> Option<(SymmetricAlgorithm,
2516                              SessionKey,
2517                              Option<Cert>)>
2518    {
2519        let keyid: KeyID = keypair.public().fingerprint().into();
2520        let (algo, sk) = pkesk.decrypt(keypair, algo_hint)
2521            .and_then(|(algo, sk)| {
2522                if decrypt(algo, &sk) { Some((algo, sk)) } else { None }
2523            })?;
2524
2525        Some((algo.or(algo_hint).unwrap(), sk,
2526              self.identities.get(&keyid).map(|cert| cert.clone())))
2527    }
2528
2529    /// Dumps the session key.
2530    fn dump_session_key(&mut self, algo: SymmetricAlgorithm, sk: &SessionKey)
2531                        -> Result<()> {
2532        self.session_key = Some(sop::SessionKey::new(algo, sk)?);
2533        Ok(())
2534    }
2535}
2536
2537impl VerificationHelper for Helper {
2538    fn get_certs(&mut self, ids: &[openpgp::KeyHandle])
2539                 -> openpgp::Result<Vec<Cert>> {
2540        self.vhelper.get_certs(ids)
2541    }
2542    fn check(&mut self, structure: MessageStructure)
2543             -> openpgp::Result<()> {
2544        self.vhelper.check(structure)
2545    }
2546}
2547
2548impl DecryptionHelper for Helper {
2549    fn decrypt(&mut self, pkesks: &[PKESK], skesks: &[SKESK],
2550               algo_hint: Option<SymmetricAlgorithm>,
2551               decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
2552               -> openpgp::Result<Option<Cert>>
2553    {
2554        let mut error = Error::CannotDecrypt;
2555
2556        // First, try all supplied session keys.
2557        while let Some(sk) = self.session_keys.pop() {
2558            let algo = SymmetricAlgorithm::from(sk.algorithm());
2559            let sk = SessionKey::from(sk.key());
2560            if decrypt(Some(algo), &sk) {
2561                self.dump_session_key(algo, &sk)?;
2562                return Ok(None);
2563            }
2564        }
2565
2566        // Second, we try those keys that we can use.
2567        for pkesk in pkesks {
2568            let keyid: KeyID = pkesk.recipient().into();
2569            if let Some(key) = self.secret_keys.get_mut(&keyid) {
2570                let key_ref = key.clone();
2571
2572                // Try to decrypt it using any supplied password.
2573                if key.secret().is_encrypted() {
2574                    for p in self.with_key_password.iter()
2575                        .flat_map(|p| p.variants())
2576                    {
2577                        if key.secret_mut().decrypt_in_place(&key_ref, &p.into())
2578                            .is_ok()
2579                        {
2580                            break;
2581                        }
2582                    }
2583                }
2584
2585                if ! key.secret().is_encrypted() {
2586                    if let Some((algo, sk, fp)) =
2587                        key.clone().into_keypair().ok().and_then(|mut k| {
2588                            self.try_decrypt(pkesk, algo_hint, &mut k, decrypt)
2589                        })
2590                    {
2591                        self.dump_session_key(algo, &sk)?;
2592                        return Ok(fp);
2593                    }
2594                } else {
2595                    // We could have used this key, but failed to
2596                    // unlock it.  Return the more useful error
2597                    // condition.
2598                    error = Error::KeyIsProtected;
2599                }
2600            }
2601        }
2602
2603        // Third, we try to decrypt PKESK packets with wildcard
2604        // recipients.
2605        for pkesk in pkesks.iter().filter(|p| KeyID::from(p.recipient()).is_wildcard()) {
2606            for mut key in std::mem::take(&mut self.secret_keys).into_values() {
2607                let key_ref = key.clone();
2608
2609                // Try to decrypt it using any supplied password.
2610                if key.secret().is_encrypted() {
2611                    for p in self.with_key_password.iter()
2612                        .flat_map(|p| p.variants())
2613                    {
2614                        if key.secret_mut().decrypt_in_place(&key_ref, &p.into())
2615                            .is_ok()
2616                        {
2617                            break;
2618                        }
2619                    }
2620                }
2621
2622                if ! key.secret().is_encrypted() {
2623                    if let Some((algo, sk, fp)) =
2624                        key.clone().into_keypair().ok().and_then(|mut k| {
2625                            self.try_decrypt(pkesk, algo_hint, &mut k, decrypt)
2626                        })
2627                    {
2628                        self.dump_session_key(algo, &sk)?;
2629                        return Ok(fp);
2630                    }
2631                } else {
2632                    // We could plausibly have used this key, but
2633                    // failed to unlock it.
2634                    error = Error::KeyIsProtected;
2635                }
2636            }
2637        }
2638
2639        if skesks.is_empty() {
2640            return Err(error.into());
2641        }
2642
2643        // Finally, try to decrypt using the SKESKs.
2644        for password in self.passwords.iter() {
2645            for skesk in skesks {
2646                if let Some((algo, sk)) = skesk.decrypt(password).ok()
2647                    .and_then(|(algo, sk)| {
2648                        if decrypt(algo, &sk) {
2649                            Some((algo, sk))
2650                        } else {
2651                            None
2652                        }
2653                    })
2654                {
2655                    self.dump_session_key(algo.or(algo_hint).unwrap(), &sk)?;
2656                    return Ok(None);
2657                }
2658            }
2659        }
2660
2661        Err(error.into())
2662    }
2663}
2664
2665fn into_sig_type(mode: sop::ops::SignAs) -> SignatureType {
2666    match mode {
2667        SignAs::Binary => SignatureType::Binary,
2668        SignAs::Text => SignatureType::Text,
2669    }
2670}
2671
2672fn into_isig_type(mode: sop::ops::InlineSignAs) -> SignatureType {
2673    match mode {
2674        InlineSignAs::Binary => SignatureType::Binary,
2675        InlineSignAs::Text => SignatureType::Text,
2676        InlineSignAs::ClearSigned => SignatureType::Text,
2677    }
2678}
2679
2680/// Returns the symbolic aliases for profiles.
2681fn symbolic_profiles() -> impl Iterator<Item=&'static str> {
2682    [
2683        "default",
2684        "security",
2685        "performance",
2686        "compatibility",
2687    ].into_iter()
2688}
2689
2690/// List profiles and their aliases.
2691fn list_profiles(profiles: &[(&str, &str)],
2692                 normalize: &dyn Fn(&str) -> Result<&'static str>)
2693                 -> Vec<(String, String)> {
2694    let mut p = profiles.iter()
2695        .map(|(p, d)| {
2696            // Discover aliases.
2697            let aliases = symbolic_profiles()
2698                .filter_map(|q| {
2699                    if normalize(q)
2700                        .map(|q| q == *p)
2701                        .unwrap_or(false)
2702                    {
2703                        Some(q)
2704                    } else {
2705                        None
2706                    }
2707                })
2708                .collect::<Vec<_>>();
2709
2710            let description = if aliases.is_empty() {
2711                d.to_string()
2712            } else {
2713                format!("{} (alias{}: {})",
2714                        d,
2715                        if aliases.len() > 1 { "es" } else { "" },
2716                        aliases.join(", "))
2717            };
2718
2719            (p.to_string(), description)
2720        })
2721        .collect::<Vec<_>>();
2722
2723    // Now sort the default one to the top.
2724    if let Ok(default) = normalize("default") {
2725        p.sort_by_key(|(name, _)| name != default);
2726        assert_eq!(&p[0].0, default);
2727    }
2728
2729    p
2730}
2731
2732/// Prints the error and causes, if any.
2733fn print_error_chain(sink: &mut dyn io::Write, err: &anyhow::Error)
2734                     -> io::Result<()>
2735{
2736    writeln!(sink, "           {}", err)?;
2737    for cause in err.chain().skip(1) {
2738        writeln!(sink, "  because: {}", cause)?;
2739    }
2740    Ok(())
2741}
2742
2743/// Maps Sequoia errors to Errors.
2744///
2745/// XXX: This is a bit of a friction point.  We likely need to improve
2746/// the SOP spec a little.
2747fn sop_error(sqop: &SQOP, e: anyhow::Error) -> Error {
2748    tracer!(sqop.debug, "sop_error");
2749
2750    let e = match e.downcast::<Error>() {
2751        Ok(e) => return e,
2752        Err(e) => e,
2753    };
2754
2755    t!("mapping error: {}", e);
2756
2757    let e = match e.downcast::<io::Error>() {
2758        Ok(e) => return if e.kind() == io::ErrorKind::UnexpectedEof {
2759            Error::BadData
2760        } else {
2761            e.into()
2762        },
2763        Err(e) => e,
2764    };
2765
2766    if let Some(e) = e.downcast_ref::<openpgp::Error>() {
2767        use openpgp::Error::*;
2768        return match e {
2769            InvalidArgument(_) => Error::BadData,
2770            InvalidOperation(_) => Error::BadData,
2771            MalformedPacket(_) => Error::BadData,
2772            PacketTooLarge(_, _, _) => Error::BadData,
2773
2774            UnsupportedPacketType(_) => Error::BadData,
2775
2776            // XXX: Those don't map cleanly, but close.
2777            UnsupportedHashAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2778            UnsupportedPublicKeyAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2779            UnsupportedEllipticCurve(_) => Error::UnsupportedAsymmetricAlgo,
2780            UnsupportedSymmetricAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2781            UnsupportedAEADAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2782            UnsupportedCompressionAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2783
2784            UnsupportedSignatureType(_) => Error::BadData,
2785            InvalidSessionKey(_) => Error::CannotDecrypt,
2786            MissingSessionKey(_) => Error::CannotDecrypt,
2787            MalformedMPI(_) => Error::BadData,
2788            BadSignature(_) => Error::BadData,
2789            MalformedMessage(_) => Error::BadData,
2790            MalformedCert(_) => Error::BadData,
2791            UnsupportedCert(_, _) => Error::BadData,
2792            Expired(_) => Error::BadData,
2793            NotYetLive(_) => Error::BadData,
2794            NoBindingSignature(_) => Error::BadData,
2795            InvalidKey(_) => Error::BadData,
2796            PolicyViolation(_, _) => Error::BadData,
2797            e => {
2798                t!("unknown Sequoia error");
2799                Error::BadData
2800            },
2801        };
2802    }
2803
2804    t!("untranslated error");
2805    Error::BadData
2806}
2807
2808#[cfg(test)]
2809mod tests {
2810    use std::io::Cursor;
2811    use super::*;
2812
2813    /// This is the example from the SOP spec:
2814    ///
2815    ///     sop generate-key "Alice Lovelace <alice@openpgp.example>" > alice.sec
2816    ///     sop extract-cert < alice.sec > alice.pgp
2817    ///
2818    ///     sop sign --as=text alice.sec < statement.txt > statement.txt.asc
2819    ///     sop verify announcement.txt.asc alice.pgp < announcement.txt
2820    ///
2821    ///     sop encrypt --sign-with=alice.sec bob.pgp < msg.eml > encrypted.asc
2822    ///     sop decrypt alice.sec < ciphertext.asc > cleartext.out
2823    #[test]
2824    fn sop_examples() -> Result<()> {
2825        let sop = SQOP::default();
2826
2827        let alice_sec = sop.generate_key()?
2828            .userid("Alice Lovelace <alice@openpgp.example>")
2829            .generate()?;
2830        let alice_pgp = sop.extract_cert()?
2831            .keys(&alice_sec)?;
2832
2833        let bob_sec = sop.generate_key()?
2834            .userid("Bob Babbage <bob@openpgp.example>")
2835            .generate()?;
2836        let bob_pgp = sop.extract_cert()?
2837            .keys(&bob_sec)?;
2838
2839        let statement = b"Hello World :)";
2840        let mut data = Cursor::new(&statement);
2841        let (_micalg, signature) = sop.sign()?
2842            .mode(SignAs::Text)
2843            .keys(&alice_sec)?
2844            .data(&mut data)?;
2845
2846        let verifications = sop.verify()?
2847            .certs(&alice_pgp)?
2848            .signatures(&signature)?
2849            .data(&mut Cursor::new(&statement))?;
2850        assert_eq!(verifications.len(), 1);
2851
2852        let mut statement_cur = Cursor::new(&statement);
2853        let (_session_key, ciphertext) = sop.encrypt()?
2854            .sign_with_keys(&alice_sec)?
2855            .with_certs(&bob_pgp)?
2856            .plaintext(&mut statement_cur)?
2857            .to_vec()?;
2858
2859        let mut ciphertext_cur = Cursor::new(&ciphertext);
2860        let (_, plaintext) = sop.decrypt()?
2861            .with_keys(&bob_sec)?
2862            .ciphertext(&mut ciphertext_cur)?
2863            .to_vec()?;
2864        assert_eq!(&plaintext, statement);
2865
2866        Ok(())
2867    }
2868
2869    #[test]
2870    fn issue_29() -> Result<()> {
2871        let sop = SQOP::default();
2872
2873        let alice_sec = sop.generate_key()?
2874            .userid("Alice Lovelace <alice@openpgp.example>")
2875            .generate()?;
2876        let alice_pgp = sop.extract_cert()?
2877            .keys(&alice_sec)?;
2878
2879        let no_signature = b"\n";
2880        assert!(matches!(sop.inline_verify()?
2881                         .certs(&alice_pgp)?
2882                         .message(&mut Cursor::new(&no_signature))
2883                         .and_then(|ready| ready.to_vec()),
2884                         Err(sop::errors::Error::BadData)));
2885
2886        Ok(())
2887    }
2888
2889    #[test]
2890    fn test_pqc() -> Result<()> {
2891        if ! PublicKeyAlgorithm::MLDSA65_Ed25519.is_supported() {
2892            eprintln!("MLDSA65_Ed25519 is not supported, skipping.");
2893            return Ok(());
2894        }
2895
2896        let sop = SQOP::default();
2897
2898        let alice_sec = sop.generate_key()?
2899            .profile("rfc9980")?
2900            .userid("Alice Lovelace <alice@openpgp.example>")
2901            .generate()?;
2902        let alice_pgp = sop.extract_cert()?
2903            .keys(&alice_sec)?;
2904
2905        let statement = b"Hello World :)";
2906        let mut data = Cursor::new(&statement);
2907        let (_micalg, signature) = sop.sign()?
2908            .mode(SignAs::Text)
2909            .keys(&alice_sec)?
2910            .data(&mut data)?;
2911
2912        let verifications = sop.verify()?
2913            .certs(&alice_pgp)?
2914            .signatures(&signature)?
2915            .data(&mut Cursor::new(&statement))?;
2916        assert_eq!(verifications.len(), 1);
2917
2918        let mut statement_cur = Cursor::new(&statement);
2919        let (_session_key, ciphertext) = sop.encrypt()?
2920            .sign_with_keys(&alice_sec)?
2921            .with_certs(&alice_pgp)?
2922            .plaintext(&mut statement_cur)?
2923            .to_vec()?;
2924
2925        let mut ciphertext_cur = Cursor::new(&ciphertext);
2926        let (_, plaintext) = sop.decrypt()?
2927            .with_keys(&alice_sec)?
2928            .ciphertext(&mut ciphertext_cur)?
2929            .to_vec()?;
2930        assert_eq!(&plaintext, statement);
2931
2932        Ok(())
2933    }
2934}