sequoia_openpgp/cert/amalgamation/key/
iter.rs

1use std::fmt;
2use std::convert::TryInto;
3use std::time::SystemTime;
4use std::borrow::Borrow;
5use std::slice;
6
7use crate::{
8    KeyHandle,
9    types::RevocationStatus,
10    packet::key,
11    types::KeyFlags,
12    cert::prelude::*,
13    policy::Policy,
14};
15
16/// Evaluates whether to skip the use of a secret key when filtering.
17///
18/// This function takes three optional boolean values, indicating whether
19/// an encrypted secret is present,
20/// whether to filter for encrypted secret keys
21/// and whether to filter for unencrypted secret keys.
22///
23/// An optional string provides context in the case where a key is skipped.
24fn skip_secret(
25    have_secret_encrypted: Option<bool>,
26    want_encrypted_key: Option<bool>,
27    want_unencrypted_secret: Option<bool>,
28) -> Option<&'static str> {
29    match (have_secret_encrypted, want_encrypted_key, want_unencrypted_secret) {
30        (Some(_), Some(true), Some(true))
31        | (_, None, None)
32        | (Some(true), Some(true), _)
33        | (Some(true), None, Some(false))
34        | (Some(false), _, Some(true))
35        | (Some(false), Some(false), None) => None,  // do not skip the key
36        (Some(true), Some(false), _) | (Some(true), None, Some(true)) => {
37            Some("Encrypted secret... skipping.")
38        }
39        (Some(false), _, Some(false)) | (Some(false), Some(true), None) => {
40            Some("Unencrypted secret... skipping.")
41        }
42        (None, Some(_), None)
43        | (None, None, Some(_))
44        | (None, Some(_), Some(_)) => {
45            Some("No secret... skipping.")
46        }
47    }
48}
49
50/// An iterator over `Key`s.
51///
52/// An iterator over [`KeyAmalgamation`]s.
53///
54/// A `KeyAmalgamationIter` is like a [`ComponentAmalgamationIter`],
55/// but specialized for keys.  Refer to the [module documentation] for
56/// an explanation of why a different type is necessary.
57///
58/// Using the [`KeyAmalgamationIter::with_policy`], it is possible to
59/// change the iterator to only return [`KeyAmalgamation`]s for valid
60/// `Key`s.  In this case, `KeyAmalgamationIter::with_policy`
61/// transforms the `KeyAmalgamationIter` into a
62/// [`ValidKeyAmalgamationIter`], which returns
63/// [`ValidKeyAmalgamation`]s.  `ValidKeyAmalgamation` offers
64/// additional filters.
65///
66/// `KeyAmalgamationIter` supports other filters.  For instance
67/// [`KeyAmalgamationIter::secret`] filters on whether secret key
68/// material is present, [`KeyAmalgamationIter::encrypted_secret`]
69/// filters on whether secret key material is present and encrypted, and
70/// [`KeyAmalgamationIter::unencrypted_secret`] filters on whether
71/// secret key material is present and unencrypted.  Of course, since
72/// `KeyAmalgamationIter` implements `Iterator`, it is possible to use
73/// [`Iterator::filter`] to implement custom filters.
74///
75/// `KeyAmalgamationIter` follows the builder pattern.  There is no
76/// need to explicitly finalize it: it already implements the
77/// `Iterator` trait.
78///
79/// A `KeyAmalgamationIter` is returned by [`Cert::keys`].
80///
81/// [`ComponentAmalgamationIter`]: super::super::ComponentAmalgamationIter
82/// [module documentation]: super
83/// [`KeyAmalgamationIter::with_policy`]: super::ValidateAmalgamation
84/// [`KeyAmalgamationIter::secret`]: KeyAmalgamationIter::secret()
85/// [`KeyAmalgamationIter::unencrypted_secret`]: KeyAmalgamationIter::unencrypted_secret()
86/// [`Iterator::filter`]: std::iter::Iterator::filter()
87/// [`Cert::keys`]: super::super::Cert::keys()
88pub struct KeyAmalgamationIter<'a, P, R>
89    where P: key::KeyParts,
90          R: key::KeyRole,
91{
92    // This is an option to make it easier to create an empty KeyAmalgamationIter.
93    cert: Option<&'a Cert>,
94    primary: bool,
95    subkey_iter: slice::Iter<'a, KeyBundle<key::PublicParts,
96                                           key::SubordinateRole>>,
97
98    // If not None, filters by whether a key has an encrypted secret.
99    encrypted_secret: Option<bool>,
100
101    // If not None, filters by whether a key has an unencrypted
102    // secret.
103    unencrypted_secret: Option<bool>,
104
105    /// Only return keys in this set.
106    key_handles: Vec<KeyHandle>,
107
108    // If not None, filters by whether we support the key's asymmetric
109    // algorithm.
110    supported: Option<bool>,
111
112    _p: std::marker::PhantomData<P>,
113    _r: std::marker::PhantomData<R>,
114}
115assert_send_and_sync!(KeyAmalgamationIter<'_, P, R>
116     where P: key::KeyParts,
117           R: key::KeyRole,
118);
119
120impl<'a, P, R> fmt::Debug for KeyAmalgamationIter<'a, P, R>
121    where P: key::KeyParts,
122          R: key::KeyRole,
123{
124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125        f.debug_struct("KeyAmalgamationIter")
126            .field("encrypted_secret", &self.encrypted_secret)
127            .field("unencrypted_secret", &self.unencrypted_secret)
128            .field("key_handles", &self.key_handles)
129            .field("supported", &self.supported)
130            .finish()
131    }
132}
133
134macro_rules! impl_iterator {
135    ($parts:path, $role:path, $item:ty) => {
136        impl<'a> Iterator for KeyAmalgamationIter<'a, $parts, $role>
137        {
138            type Item = $item;
139
140            fn next(&mut self) -> Option<Self::Item> {
141                // We unwrap the result of the conversion.  But, this
142                // is safe by construction: next_common only returns
143                // keys that can be correctly converted.
144                self.next_common().map(|k| k.try_into().expect("filtered"))
145            }
146        }
147    }
148}
149
150impl_iterator!(key::PublicParts, key::PrimaryRole,
151               PrimaryKeyAmalgamation<'a, key::PublicParts>);
152impl_iterator!(key::SecretParts, key::PrimaryRole,
153               PrimaryKeyAmalgamation<'a, key::SecretParts>);
154impl_iterator!(key::UnspecifiedParts, key::PrimaryRole,
155               PrimaryKeyAmalgamation<'a, key::UnspecifiedParts>);
156
157impl_iterator!(key::PublicParts, key::SubordinateRole,
158               SubordinateKeyAmalgamation<'a, key::PublicParts>);
159impl_iterator!(key::SecretParts, key::SubordinateRole,
160               SubordinateKeyAmalgamation<'a, key::SecretParts>);
161impl_iterator!(key::UnspecifiedParts, key::SubordinateRole,
162               SubordinateKeyAmalgamation<'a, key::UnspecifiedParts>);
163
164impl_iterator!(key::PublicParts, key::UnspecifiedRole,
165               ErasedKeyAmalgamation<'a, key::PublicParts>);
166impl_iterator!(key::SecretParts, key::UnspecifiedRole,
167               ErasedKeyAmalgamation<'a, key::SecretParts>);
168impl_iterator!(key::UnspecifiedParts, key::UnspecifiedRole,
169               ErasedKeyAmalgamation<'a, key::UnspecifiedParts>);
170
171impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
172    where P: key::KeyParts,
173          R: key::KeyRole,
174{
175    fn next_common(&mut self) -> Option<ErasedKeyAmalgamation<'a, key::PublicParts>>
176    {
177        tracer!(false, "KeyAmalgamationIter::next", 0);
178        t!("KeyAmalgamationIter: {:?}", self);
179
180        let cert = self.cert?;
181
182        loop {
183            let ka : ErasedKeyAmalgamation<key::PublicParts>
184                = if ! self.primary {
185                    self.primary = true;
186                    PrimaryKeyAmalgamation::new(cert).into()
187                } else {
188                    SubordinateKeyAmalgamation::new(
189                        cert, self.subkey_iter.next()?).into()
190                };
191
192            t!("Considering key: {:?}", ka.key());
193
194            if ! self.key_handles.is_empty()
195                && ! self.key_handles.iter()
196                    .any(|h| h.aliases(ka.key().key_handle()))
197            {
198                t!("{} is not one of the keys that we are looking for ({:?})",
199                   ka.key().fingerprint(), self.key_handles);
200                continue;
201            }
202
203            if let Some(want_supported) = self.supported {
204                if ka.key().pk_algo().is_supported() {
205                    // It is supported.
206                    if ! want_supported {
207                        t!("PK algo is supported... skipping.");
208                        continue;
209                    }
210                } else if want_supported {
211                    t!("PK algo is not supported... skipping.");
212                    continue;
213                }
214            }
215
216            if let Some(msg) = skip_secret(
217                ka.key().optional_secret().map(|x| x.is_encrypted()),
218                self.encrypted_secret,
219                self.unencrypted_secret,
220            ) {
221                t!(msg);
222                continue;
223            }
224
225            return Some(ka);
226        }
227    }
228}
229
230impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
231    where P: key::KeyParts,
232          R: key::KeyRole,
233{
234    /// Returns a new `KeyAmalgamationIter` instance.
235    pub(crate) fn new(cert: &'a Cert) -> Self where Self: 'a {
236        KeyAmalgamationIter {
237            cert: Some(cert),
238            primary: false,
239            subkey_iter: cert.subkeys.iter(),
240
241            // The filters.
242            encrypted_secret: None,
243            unencrypted_secret: None,
244            key_handles: Default::default(),
245            supported: None,
246
247            _p: std::marker::PhantomData,
248            _r: std::marker::PhantomData,
249        }
250    }
251
252    /// Changes the iterator to only return keys with secret key
253    /// material.
254    ///
255    /// # Examples
256    ///
257    /// ```rust
258    /// # use sequoia_openpgp as openpgp;
259    /// # use openpgp::Result;
260    /// # use openpgp::cert::prelude::*;
261    /// # fn main() -> Result<()> {
262    /// #     let (cert, _) =
263    /// #         CertBuilder::new().set_password(Some("password".into()))
264    /// #         .generate()?;
265    /// for ka in cert.keys().secret() {
266    ///     // Use it.
267    /// }
268    /// #     assert!(cert.keys().secret().count() == 1);
269    /// #
270    /// #     let (cert, _) = CertBuilder::new().generate()?;
271    /// #     assert!(cert.keys().secret().count() == 1);
272    /// #     Ok(())
273    /// # }
274    /// ```
275    pub fn secret(self) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
276        KeyAmalgamationIter {
277            cert: self.cert,
278            primary: self.primary,
279            subkey_iter: self.subkey_iter,
280
281            // The filters.
282            encrypted_secret: Some(true),
283            unencrypted_secret: Some(true),
284            key_handles: self.key_handles,
285            supported: self.supported,
286
287            _p: std::marker::PhantomData,
288            _r: std::marker::PhantomData,
289        }
290    }
291
292    /// Changes the iterator to only return keys with encrypted secret key
293    /// material.
294    ///
295    /// # Examples
296    ///
297    /// ```rust
298    /// # use sequoia_openpgp as openpgp;
299    /// # use openpgp::Result;
300    /// # use openpgp::cert::prelude::*;
301    /// # fn main() -> Result<()> {
302    /// #     let (cert, _) =
303    /// #         CertBuilder::new().set_password(Some("password".into()))
304    /// #         .generate()?;
305    /// for ka in cert.keys().encrypted_secret() {
306    ///     // Use it.
307    /// }
308    /// #     assert!(cert.keys().encrypted_secret().count() == 1);
309    /// #     Ok(())
310    /// # }
311    /// ```
312    pub fn encrypted_secret(
313        self,
314    ) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
315        KeyAmalgamationIter {
316            cert: self.cert,
317            primary: self.primary,
318            subkey_iter: self.subkey_iter,
319
320            // The filters.
321            encrypted_secret: Some(true),
322            unencrypted_secret: self.unencrypted_secret,
323            key_handles: self.key_handles,
324            supported: self.supported,
325
326            _p: std::marker::PhantomData,
327            _r: std::marker::PhantomData,
328        }
329    }
330
331    /// Changes the iterator to only return keys with unencrypted
332    /// secret key material.
333    ///
334    /// # Examples
335    ///
336    /// ```rust
337    /// # use sequoia_openpgp as openpgp;
338    /// # use openpgp::Result;
339    /// # use openpgp::cert::prelude::*;
340    /// # fn main() -> Result<()> {
341    /// #     let (cert, _) =
342    /// #         CertBuilder::new().generate()?;
343    /// for ka in cert.keys().unencrypted_secret() {
344    ///     // Use it.
345    /// }
346    /// #     assert!(cert.keys().secret().unencrypted_secret().count() == 1);
347    /// #     Ok(())
348    /// # }
349    /// ```
350    pub fn unencrypted_secret(self) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
351        KeyAmalgamationIter {
352            cert: self.cert,
353            primary: self.primary,
354            subkey_iter: self.subkey_iter,
355
356            // The filters.
357            encrypted_secret: self.encrypted_secret,
358            unencrypted_secret: Some(true),
359            key_handles: self.key_handles,
360            supported: self.supported,
361
362            _p: std::marker::PhantomData,
363            _r: std::marker::PhantomData,
364        }
365    }
366
367    /// Changes the iterator to only return a key if it matches one of
368    /// the specified `KeyHandle`s.
369    ///
370    /// This function is cumulative.  If you call this function (or
371    /// [`key_handles`]) multiple times, then the iterator returns a key
372    /// if it matches *any* of the specified [`KeyHandle`s].
373    ///
374    /// This function uses [`KeyHandle::aliases`] to compare key
375    /// handles.
376    ///
377    /// # Examples
378    ///
379    /// ```rust
380    /// # use sequoia_openpgp as openpgp;
381    /// # use openpgp::Result;
382    /// # use openpgp::cert::prelude::*;
383    /// # fn main() -> Result<()> {
384    /// #     let (cert, _) =
385    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
386    /// #         .generate()?;
387    /// # let key_handle = cert.primary_key().key().key_handle();
388    /// # let mut i = 0;
389    /// for ka in cert.keys().key_handle(key_handle) {
390    ///     // Use it.
391    /// #   i += 1;
392    /// }
393    /// # assert_eq!(i, 1);
394    /// #     Ok(())
395    /// # }
396    /// ```
397    ///
398    /// [`KeyHandle`s]: super::super::super::KeyHandle
399    /// [`key_handles`]: KeyAmalgamationIter::key_handles()
400    /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
401    pub fn key_handle<H>(mut self, h: H) -> Self
402        where H: Into<KeyHandle>
403    {
404        self.key_handles.push(h.into());
405        self
406    }
407
408    /// Changes the iterator to only return a key if it matches one of
409    /// the specified `KeyHandle`s.
410    ///
411    /// If the given `handles` iterator is empty, the set of returned
412    /// keys is not constrained.
413    ///
414    /// This function is cumulative.  If you call this function (or
415    /// [`key_handle`]) multiple times, then the iterator returns a key
416    /// if it matches *any* of the specified [`KeyHandle`s].
417    ///
418    /// This function uses [`KeyHandle::aliases`] to compare key
419    /// handles.
420    ///
421    /// # Examples
422    ///
423    /// ```rust
424    /// # use sequoia_openpgp as openpgp;
425    /// # use openpgp::Result;
426    /// # use openpgp::cert::prelude::*;
427    /// # fn main() -> Result<()> {
428    /// #     let (cert, _) =
429    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
430    /// #         .generate()?;
431    /// # let key_handles = &[cert.primary_key().key().key_handle()][..];
432    /// # let mut i = 0;
433    /// for ka in cert.keys().key_handles(key_handles) {
434    ///     // Use it.
435    /// #   i += 1;
436    /// }
437    /// # assert_eq!(i, 1);
438    /// #     Ok(())
439    /// # }
440    /// ```
441    ///
442    /// [`KeyHandle`s]: super::super::super::KeyHandle
443    /// [`key_handle`]: KeyAmalgamationIter::key_handle()
444    /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
445    pub fn key_handles<H, K>(mut self, handles: H) -> Self
446    where
447        H: IntoIterator<Item=K>,
448        K: Borrow<KeyHandle>,
449    {
450        let mut handles = handles.into_iter()
451            .map(|h| h.borrow().clone())
452            .collect::<Vec<_>>();
453
454        self.key_handles.append(&mut handles);
455        self
456    }
457
458    /// Changes the iterator to only return a key if it is supported
459    /// by Sequoia's cryptographic backend.
460    ///
461    /// Which public key encryption algorithms Sequoia supports
462    /// depends on the cryptographic backend selected at compile time.
463    /// This filter makes sure that only supported keys are returned.
464    ///
465    /// # Examples
466    ///
467    /// ```rust
468    /// # fn main() -> sequoia_openpgp::Result<()> {
469    /// # use sequoia_openpgp as openpgp;
470    /// # use openpgp::cert::prelude::*;
471    /// #     let (cert, _) =
472    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
473    /// #         .generate()?;
474    /// # let mut i = 0;
475    /// for ka in cert.keys().supported() {
476    ///     // Use it.
477    /// #   i += 1;
478    /// }
479    /// # assert_eq!(i, 3);
480    /// # Ok(()) }
481    /// ```
482    pub fn supported(mut self) -> Self {
483        self.supported = Some(true);
484        self
485    }
486
487    /// Changes the iterator to only return subkeys.
488    ///
489    /// This function also changes the return type.  Instead of the
490    /// iterator returning a [`ErasedKeyAmalgamation`], it returns a
491    /// [`SubordinateKeyAmalgamation`].
492    ///
493    /// # Examples
494    ///
495    /// ```rust
496    /// # use sequoia_openpgp as openpgp;
497    /// # use openpgp::Result;
498    /// # use openpgp::cert::prelude::*;
499    /// #
500    /// # fn main() -> Result<()> {
501    /// #      let (cert, _) = CertBuilder::new()
502    /// #          .add_signing_subkey()
503    /// #          .add_certification_subkey()
504    /// #          .add_transport_encryption_subkey()
505    /// #          .add_storage_encryption_subkey()
506    /// #          .add_authentication_subkey()
507    /// #          .generate()?;
508    /// # let mut i = 0;
509    /// for ka in cert.keys().subkeys() {
510    ///     // Use it.
511    ///     assert!(! ka.primary());
512    /// #   i += 1;
513    /// }
514    /// # assert_eq!(i, 5);
515    /// #     Ok(())
516    /// # }
517    /// ```
518    ///
519    pub fn subkeys(self) -> KeyAmalgamationIter<'a, P, key::SubordinateRole> {
520        KeyAmalgamationIter {
521            cert: self.cert,
522            primary: true,
523            subkey_iter: self.subkey_iter,
524
525            // The filters.
526            encrypted_secret: self.encrypted_secret,
527            unencrypted_secret: self.unencrypted_secret,
528            key_handles: self.key_handles,
529            supported: self.supported,
530
531            _p: std::marker::PhantomData,
532            _r: std::marker::PhantomData,
533        }
534    }
535
536    /// Changes the iterator to only return valid `Key`s.
537    ///
538    /// If `time` is None, then the current time is used.
539    ///
540    /// This also makes a number of additional filters like [`alive`]
541    /// and [`revoked`] available.
542    ///
543    /// Refer to the [`ValidateAmalgamation`] trait for a definition
544    /// of a valid component.
545    ///
546    /// # Examples
547    ///
548    /// ```
549    /// # use sequoia_openpgp as openpgp;
550    /// # use openpgp::cert::prelude::*;
551    /// use openpgp::policy::StandardPolicy;
552    /// #
553    /// # fn main() -> openpgp::Result<()> {
554    /// let p = &StandardPolicy::new();
555    ///
556    /// #     let (cert, _) =
557    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
558    /// #         .generate()?;
559    /// #     let fpr = cert.fingerprint();
560    /// // Iterate over all valid User Attributes.
561    /// for ka in cert.keys().with_policy(p, None) {
562    ///     // ka is a `ValidKeyAmalgamation`, specifically, an
563    ///     // `ValidErasedKeyAmalgamation`.
564    /// }
565    /// #     Ok(())
566    /// # }
567    /// ```
568    ///
569    /// [`ValidateAmalgamation`]: super::ValidateAmalgamation
570    /// [`alive`]: ValidKeyAmalgamationIter::alive()
571    /// [`revoked`]: ValidKeyAmalgamationIter::revoked()
572    pub fn with_policy<T>(self, policy: &'a dyn Policy, time: T)
573        -> ValidKeyAmalgamationIter<'a, P, R>
574        where T: Into<Option<SystemTime>>
575    {
576        ValidKeyAmalgamationIter {
577            cert: self.cert,
578            primary: self.primary,
579            subkey_iter: self.subkey_iter,
580
581            policy,
582            time: time.into().unwrap_or_else(crate::now),
583
584            // The filters.
585            encrypted_secret: self.encrypted_secret,
586            unencrypted_secret: self.unencrypted_secret,
587            key_handles: self.key_handles,
588            supported: self.supported,
589            flags: None,
590            alive: None,
591            revoked: None,
592
593            _p: self._p,
594            _r: self._r,
595        }
596    }
597}
598
599/// An iterator over valid `Key`s.
600///
601/// An iterator over [`ValidKeyAmalgamation`]s.
602///
603/// A `ValidKeyAmalgamationIter` is a [`KeyAmalgamationIter`]
604/// that includes a [`Policy`] and a reference time, which it firstly
605/// uses to only return valid `Key`s.  (For a definition of valid
606/// keys, see the documentation for [`ValidateAmalgamation`].)
607///
608/// A `ValidKeyAmalgamationIter` also provides additional
609/// filters based on information available in the `Key`s' binding
610/// signatures.  For instance, [`ValidKeyAmalgamationIter::revoked`]
611/// filters the returned `Key`s by whether they are revoked.
612/// And, [`ValidKeyAmalgamationIter::alive`] changes the iterator to
613/// only return `Key`s that are live.
614///
615/// `ValidKeyAmalgamationIter` follows the builder pattern.  But,
616/// there is no need to explicitly finalize it: it already implements
617/// the `Iterator` trait.
618///
619/// A `ValidKeyAmalgamationIter` is returned by
620/// [`KeyAmalgamationIter::with_policy`] and [`ValidCert::keys`].
621///
622/// # Examples
623///
624/// Find a key that we can use to sign a document:
625///
626/// ```
627/// # use sequoia_openpgp as openpgp;
628/// # use openpgp::cert::prelude::*;
629/// use openpgp::policy::StandardPolicy;
630/// use openpgp::types::RevocationStatus;
631///
632/// # fn main() -> openpgp::Result<()> {
633/// let p = &StandardPolicy::new();
634///
635/// #     let (cert, _) =
636/// #         CertBuilder::general_purpose(Some("alice@example.org"))
637/// #         .generate()?;
638/// # let mut i = 0;
639/// // The certificate *and* keys need to be valid.
640/// let cert = cert.with_policy(p, None)?;
641///
642/// if let RevocationStatus::Revoked(_) = cert.revocation_status() {
643///     // Certificate is revoked.
644/// } else if let Err(_err) = cert.alive() {
645///     // The certificate is not alive.
646/// } else {
647///     // Iterate over all valid keys.
648///     //
649///     // Note: using the combinator interface (instead of checking
650///     // the individual keys) makes it harder to report exactly why no
651///     // key was usable.
652///     for ka in cert.keys()
653///         // Not revoked.
654///         .revoked(false)
655///         // Alive.
656///         .alive()
657///         // Be signing capable.
658///         .for_signing()
659///         // And have unencrypted secret material.
660///         .unencrypted_secret()
661///     {
662///         // We can use it.
663/// #       i += 1;
664///     }
665/// }
666/// # assert_eq!(i, 1);
667/// #     Ok(())
668/// # }
669/// ```
670///
671/// [`Policy`]: crate::policy::Policy
672/// [`ValidateAmalgamation`]: super::ValidateAmalgamation
673/// [`ValidKeyAmalgamationIter::revoked`]: ValidKeyAmalgamationIter::revoked()
674/// [`ValidKeyAmalgamationIter::alive`]: ValidKeyAmalgamationIter::alive()
675/// [`KeyAmalgamationIter::with_policy`]: KeyAmalgamationIter::with_policy()
676/// [`ValidCert::keys`]: super::super::ValidCert::keys()
677pub struct ValidKeyAmalgamationIter<'a, P, R>
678    where P: key::KeyParts,
679          R: key::KeyRole,
680{
681    // This is an option to make it easier to create an empty ValidKeyAmalgamationIter.
682    cert: Option<&'a Cert>,
683    primary: bool,
684    subkey_iter: slice::Iter<'a, KeyBundle<key::PublicParts,
685                                           key::SubordinateRole>>,
686
687    // The policy.
688    policy: &'a dyn Policy,
689
690    // The time.
691    time: SystemTime,
692
693    // If not None, filters by whether a key has an encrypted secret.
694    encrypted_secret: Option<bool>,
695
696    // If not None, filters by whether a key has an unencrypted
697    // secret.
698    unencrypted_secret: Option<bool>,
699
700    /// Only return keys in this set.
701    key_handles: Vec<KeyHandle>,
702
703    // If not None, filters by whether we support the key's asymmetric
704    // algorithm.
705    supported: Option<bool>,
706
707    // If not None, only returns keys with the specified flags.
708    flags: Option<KeyFlags>,
709
710    // If not None, filters by whether a key is alive at time `t`.
711    alive: Option<()>,
712
713    // If not None, filters by whether the key is revoked or not at
714    // time `t`.
715    revoked: Option<bool>,
716
717    _p: std::marker::PhantomData<P>,
718    _r: std::marker::PhantomData<R>,
719}
720assert_send_and_sync!(ValidKeyAmalgamationIter<'_, P, R>
721     where P: key::KeyParts,
722           R: key::KeyRole,
723);
724
725impl<'a, P, R> fmt::Debug for ValidKeyAmalgamationIter<'a, P, R>
726    where P: key::KeyParts,
727          R: key::KeyRole,
728{
729    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
730        f.debug_struct("ValidKeyAmalgamationIter")
731            .field("policy", &self.policy)
732            .field("time", &self.time)
733            .field("encrypted_secret", &self.encrypted_secret)
734            .field("unencrypted_secret", &self.unencrypted_secret)
735            .field("key_handles", &self.key_handles)
736            .field("supported", &self.supported)
737            .field("flags", &self.flags)
738            .field("alive", &self.alive)
739            .field("revoked", &self.revoked)
740            .finish()
741    }
742}
743
744macro_rules! impl_iterator {
745    ($parts:path, $role:path, $item:ty) => {
746        impl<'a> Iterator for ValidKeyAmalgamationIter<'a, $parts, $role>
747        {
748            type Item = $item;
749
750            fn next(&mut self) -> Option<Self::Item> {
751                // We unwrap the result of the conversion.  But, this
752                // is safe by construction: next_common only returns
753                // keys that can be correctly converted.
754                self.next_common().map(|k| k.try_into().expect("filtered"))
755            }
756        }
757    }
758}
759
760impl_iterator!(key::PublicParts, key::PrimaryRole,
761               ValidPrimaryKeyAmalgamation<'a, key::PublicParts>);
762impl_iterator!(key::SecretParts, key::PrimaryRole,
763               ValidPrimaryKeyAmalgamation<'a, key::SecretParts>);
764impl_iterator!(key::UnspecifiedParts, key::PrimaryRole,
765               ValidPrimaryKeyAmalgamation<'a, key::UnspecifiedParts>);
766
767impl_iterator!(key::PublicParts, key::SubordinateRole,
768               ValidSubordinateKeyAmalgamation<'a, key::PublicParts>);
769impl_iterator!(key::SecretParts, key::SubordinateRole,
770               ValidSubordinateKeyAmalgamation<'a, key::SecretParts>);
771impl_iterator!(key::UnspecifiedParts, key::SubordinateRole,
772               ValidSubordinateKeyAmalgamation<'a, key::UnspecifiedParts>);
773
774impl_iterator!(key::PublicParts, key::UnspecifiedRole,
775               ValidErasedKeyAmalgamation<'a, key::PublicParts>);
776impl_iterator!(key::SecretParts, key::UnspecifiedRole,
777               ValidErasedKeyAmalgamation<'a, key::SecretParts>);
778impl_iterator!(key::UnspecifiedParts, key::UnspecifiedRole,
779               ValidErasedKeyAmalgamation<'a, key::UnspecifiedParts>);
780
781impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
782    where P: key::KeyParts,
783          R: key::KeyRole,
784{
785    fn next_common(&mut self)
786        -> Option<ValidErasedKeyAmalgamation<'a, key::PublicParts>>
787    {
788        tracer!(false, "ValidKeyAmalgamationIter::next", 0);
789        t!("ValidKeyAmalgamationIter: {:?}", self);
790
791        let cert = self.cert?;
792
793        if let Some(flags) = self.flags.as_ref() {
794            if flags.is_empty() {
795                // Nothing to do.
796                t!("short circuiting: flags is empty");
797                return None;
798            }
799        }
800
801        loop {
802            let ka = if ! self.primary {
803                self.primary = true;
804                let ka : ErasedKeyAmalgamation<'a, key::PublicParts>
805                    = PrimaryKeyAmalgamation::new(cert).into();
806                match ka.with_policy(self.policy, self.time) {
807                    Ok(ka) => ka,
808                    Err(err) => {
809                        // The primary key is bad.  Abort.
810                        t!("Getting primary key: {:?}", err);
811                        return None;
812                    }
813                }
814            } else {
815                let ka : ErasedKeyAmalgamation<'a, key::PublicParts>
816                    = SubordinateKeyAmalgamation::new(
817                        cert, self.subkey_iter.next()?).into();
818                match ka.with_policy(self.policy, self.time) {
819                    Ok(ka) => ka,
820                    Err(err) => {
821                        // The subkey is bad, abort.
822                        t!("Getting subkey: {:?}", err);
823                        continue;
824                    }
825                }
826            };
827
828            let key = ka.key();
829            t!("Considering key: {:?}", key);
830
831            if ! self.key_handles.is_empty()
832                && ! self.key_handles.iter()
833                    .any(|h| h.aliases(key.key_handle()))
834            {
835                t!("{} is not one of the keys that we are looking for ({:?})",
836                   key.key_handle(), self.key_handles);
837                continue;
838            }
839
840            if let Some(want_supported) = self.supported {
841                if ka.key().pk_algo().is_supported() {
842                    // It is supported.
843                    if ! want_supported {
844                        t!("PK algo is supported... skipping.");
845                        continue;
846                    }
847                } else if want_supported {
848                    t!("PK algo is not supported... skipping.");
849                    continue;
850                }
851            }
852
853            if let Some(flags) = self.flags.as_ref() {
854                if !ka.has_any_key_flag(flags) {
855                    t!("Have flags: {:?}, want flags: {:?}... skipping.",
856                       ka.key_flags(), flags);
857                    continue;
858                }
859            }
860
861            if let Some(()) = self.alive {
862                if let Err(err) = ka.alive() {
863                    t!("Key not alive: {:?}", err);
864                    continue;
865                }
866            }
867
868            if let Some(want_revoked) = self.revoked {
869                if let RevocationStatus::Revoked(_) = ka.revocation_status() {
870                    // The key is definitely revoked.
871                    if ! want_revoked {
872                        t!("Key revoked... skipping.");
873                        continue;
874                    }
875                } else {
876                    // The key is probably not revoked.
877                    if want_revoked {
878                        t!("Key not revoked... skipping.");
879                        continue;
880                    }
881                }
882            }
883
884            if let Some(msg) = skip_secret(
885                ka.key().optional_secret().map(|x| x.is_encrypted()),
886                self.encrypted_secret,
887                self.unencrypted_secret,
888            ) {
889                t!(msg);
890                continue;
891            }
892
893            return Some(ka);
894        }
895    }
896}
897
898impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
899    where P: key::KeyParts,
900          R: key::KeyRole,
901{
902    /// Returns keys that have the at least one of the flags specified
903    /// in `flags`.
904    ///
905    /// If you call this function (or one of `for_certification`,
906    /// `for_signing`, etc.) multiple times, the *union* of
907    /// the values is used.
908    ///
909    /// Note: [Section 10.1 of RFC 9580] says that the primary key is
910    /// certification capable independent of the `Key Flags`
911    /// subpacket:
912    ///
913    /// > In a V4 key, the primary key MUST be a key capable of
914    /// > certification.
915    ///
916    /// This function only reflects what is stored in the `Key Flags`
917    /// packet; it does not implicitly set this flag.  In practice,
918    /// there are keys whose primary key's `Key Flags` do not have the
919    /// certification capable flag set.  Some versions of netpgp, for
920    /// instance, create keys like this.  Sequoia's higher-level
921    /// functionality correctly handles these keys by always
922    /// considering the primary key to be certification capable.
923    /// Users of this interface should too.
924    ///
925    /// The key flags are looked up as described in
926    /// [`ValidKeyAmalgamation::key_flags`].
927    ///
928    /// # Examples
929    ///
930    /// ```
931    /// # use sequoia_openpgp as openpgp;
932    /// # use openpgp::cert::prelude::*;
933    /// use openpgp::policy::StandardPolicy;
934    /// use openpgp::types::KeyFlags;
935    ///
936    /// # fn main() -> openpgp::Result<()> {
937    /// let p = &StandardPolicy::new();
938    ///
939    /// #   let (cert, _) = CertBuilder::new()
940    /// #       .add_signing_subkey()
941    /// #       .add_certification_subkey()
942    /// #       .add_transport_encryption_subkey()
943    /// #       .add_storage_encryption_subkey()
944    /// #       .add_authentication_subkey()
945    /// #       .generate()?;
946    /// #   let mut i = 0;
947    /// for ka in cert.keys()
948    ///     .with_policy(p, None)
949    ///     .key_flags(KeyFlags::empty()
950    ///         .set_transport_encryption()
951    ///         .set_storage_encryption())
952    /// {
953    ///     // Valid encryption-capable keys.
954    /// #   i += 1;
955    /// }
956    /// # assert_eq!(i, 2);
957    /// # Ok(()) }
958    /// ```
959    ///
960    ///   [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
961    ///   [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
962    pub fn key_flags<F>(mut self, flags: F) -> Self
963        where F: Borrow<KeyFlags>
964    {
965        let flags = flags.borrow();
966        if let Some(flags_old) = self.flags {
967            self.flags = Some(flags | &flags_old);
968        } else {
969            self.flags = Some(flags.clone());
970        }
971        self
972    }
973
974    /// Returns certification-capable keys.
975    ///
976    /// If you call this function (or one of `key_flags`,
977    /// `for_signing`, etc.) multiple times, the *union* of
978    /// the values is used.
979    ///
980    /// Note: [Section 10.1 of RFC 9580] says that the primary key is
981    /// certification capable independent of the `Key Flags`
982    /// subpacket:
983    ///
984    /// > In a V4 key, the primary key MUST be a key capable of
985    /// > certification.
986    ///
987    /// This function only reflects what is stored in the `Key Flags`
988    /// packet; it does not implicitly set this flag.  In practice,
989    /// there are keys whose primary key's `Key Flags` do not have the
990    /// certification capable flag set.  Some versions of netpgp, for
991    /// instance, create keys like this.  Sequoia's higher-level
992    /// functionality correctly handles these keys by always
993    /// considering the primary key to be certification capable.
994    /// Users of this interface should too.
995    ///
996    /// The key flags are looked up as described in
997    /// [`ValidKeyAmalgamation::key_flags`].
998    ///
999    /// # Examples
1000    ///
1001    /// ```
1002    /// # use sequoia_openpgp as openpgp;
1003    /// # use openpgp::cert::prelude::*;
1004    /// use openpgp::policy::StandardPolicy;
1005    ///
1006    /// # fn main() -> openpgp::Result<()> {
1007    /// let p = &StandardPolicy::new();
1008    ///
1009    /// #   let (cert, _) = CertBuilder::new()
1010    /// #       .add_signing_subkey()
1011    /// #       .add_certification_subkey()
1012    /// #       .add_transport_encryption_subkey()
1013    /// #       .add_storage_encryption_subkey()
1014    /// #       .add_authentication_subkey()
1015    /// #       .generate()?;
1016    /// #   let mut i = 0;
1017    /// for ka in cert.keys()
1018    ///     .with_policy(p, None)
1019    ///     .for_certification()
1020    /// {
1021    ///     // Valid certification-capable keys.
1022    /// #   i += 1;
1023    /// }
1024    /// # assert_eq!(i, 2);
1025    /// # Ok(()) }
1026    /// ```
1027    ///
1028    ///   [`ValidKeyAmalgamation::for_certification`]: ValidKeyAmalgamation::for_certification()
1029    ///   [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
1030    ///   [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
1031    pub fn for_certification(self) -> Self {
1032        self.key_flags(KeyFlags::empty().set_certification())
1033    }
1034
1035    /// Returns signing-capable keys.
1036    ///
1037    /// If you call this function (or one of `key_flags`,
1038    /// `for_certification`, etc.) multiple times, the *union* of
1039    /// the values is used.
1040    ///
1041    /// Refer to [`ValidKeyAmalgamation::for_signing`] for additional
1042    /// details and caveats.
1043    ///
1044    /// # Examples
1045    ///
1046    /// ```
1047    /// # use sequoia_openpgp as openpgp;
1048    /// # use openpgp::cert::prelude::*;
1049    /// use openpgp::policy::StandardPolicy;
1050    ///
1051    /// # fn main() -> openpgp::Result<()> {
1052    /// let p = &StandardPolicy::new();
1053    ///
1054    /// #   let (cert, _) = CertBuilder::new()
1055    /// #       .add_signing_subkey()
1056    /// #       .add_certification_subkey()
1057    /// #       .add_transport_encryption_subkey()
1058    /// #       .add_storage_encryption_subkey()
1059    /// #       .add_authentication_subkey()
1060    /// #       .generate()?;
1061    /// #   let mut i = 0;
1062    /// for ka in cert.keys()
1063    ///     .with_policy(p, None)
1064    ///     .for_signing()
1065    /// {
1066    ///     // Valid signing-capable keys.
1067    /// #   i += 1;
1068    /// }
1069    /// # assert_eq!(i, 1);
1070    /// # Ok(()) }
1071    /// ```
1072    ///
1073    ///   [`ValidKeyAmalgamation::for_signing`]: ValidKeyAmalgamation::for_signing()
1074    pub fn for_signing(self) -> Self {
1075        self.key_flags(KeyFlags::empty().set_signing())
1076    }
1077
1078    /// Returns authentication-capable keys.
1079    ///
1080    /// If you call this function (or one of `key_flags`,
1081    /// `for_certification`, etc.) multiple times, the
1082    /// *union* of the values is used.
1083    ///
1084    /// Refer to [`ValidKeyAmalgamation::for_authentication`] for
1085    /// additional details and caveats.
1086    ///
1087    /// # Examples
1088    ///
1089    /// ```
1090    /// # use sequoia_openpgp as openpgp;
1091    /// # use openpgp::cert::prelude::*;
1092    /// use openpgp::policy::StandardPolicy;
1093    ///
1094    /// # fn main() -> openpgp::Result<()> {
1095    /// let p = &StandardPolicy::new();
1096    ///
1097    /// #   let (cert, _) = CertBuilder::new()
1098    /// #       .add_authentication_subkey()
1099    /// #       .add_certification_subkey()
1100    /// #       .add_transport_encryption_subkey()
1101    /// #       .add_storage_encryption_subkey()
1102    /// #       .add_authentication_subkey()
1103    /// #       .generate()?;
1104    /// #   let mut i = 0;
1105    /// for ka in cert.keys()
1106    ///     .with_policy(p, None)
1107    ///     .for_authentication()
1108    /// {
1109    ///     // Valid authentication-capable keys.
1110    /// #   i += 1;
1111    /// }
1112    /// # assert_eq!(i, 2);
1113    /// # Ok(()) }
1114    /// ```
1115    ///
1116    ///   [`ValidKeyAmalgamation::for_authentication`]: ValidKeyAmalgamation::for_authentication()
1117    pub fn for_authentication(self) -> Self {
1118        self.key_flags(KeyFlags::empty().set_authentication())
1119    }
1120
1121    /// Returns encryption-capable keys for data at rest.
1122    ///
1123    /// If you call this function (or one of `key_flags`,
1124    /// `for_certification`, etc.) multiple times, the
1125    /// *union* of the values is used.
1126    ///
1127    /// Refer to [`ValidKeyAmalgamation::for_storage_encryption`] for
1128    /// additional details and caveats.
1129    ///
1130    /// # Examples
1131    ///
1132    /// ```
1133    /// # use sequoia_openpgp as openpgp;
1134    /// # use openpgp::cert::prelude::*;
1135    /// use openpgp::policy::StandardPolicy;
1136    ///
1137    /// # fn main() -> openpgp::Result<()> {
1138    /// let p = &StandardPolicy::new();
1139    ///
1140    /// #   let (cert, _) = CertBuilder::new()
1141    /// #       .add_authentication_subkey()
1142    /// #       .add_certification_subkey()
1143    /// #       .add_transport_encryption_subkey()
1144    /// #       .add_storage_encryption_subkey()
1145    /// #       .add_authentication_subkey()
1146    /// #       .generate()?;
1147    /// #   let mut i = 0;
1148    /// for ka in cert.keys()
1149    ///     .with_policy(p, None)
1150    ///     .for_storage_encryption()
1151    /// {
1152    ///     // Valid encryption-capable keys for data at rest.
1153    /// #   i += 1;
1154    /// }
1155    /// # assert_eq!(i, 1);
1156    /// # Ok(()) }
1157    /// ```
1158    ///
1159    ///   [`ValidKeyAmalgamation::for_storage_encryption`]: ValidKeyAmalgamation::for_storage_encryption()
1160    pub fn for_storage_encryption(self) -> Self {
1161        self.key_flags(KeyFlags::empty().set_storage_encryption())
1162    }
1163
1164    /// Returns encryption-capable keys for data in transit.
1165    ///
1166    /// If you call this function (or one of `key_flags`,
1167    /// `for_certification`, etc.) multiple times, the
1168    /// *union* of the values is used.
1169    ///
1170    /// Refer to [`ValidKeyAmalgamation::for_transport_encryption`] for
1171    /// additional details and caveats.
1172    ///
1173    /// # Examples
1174    ///
1175    /// ```
1176    /// # use sequoia_openpgp as openpgp;
1177    /// # use openpgp::cert::prelude::*;
1178    /// use openpgp::policy::StandardPolicy;
1179    ///
1180    /// # fn main() -> openpgp::Result<()> {
1181    /// let p = &StandardPolicy::new();
1182    ///
1183    /// #   let (cert, _) = CertBuilder::new()
1184    /// #       .add_authentication_subkey()
1185    /// #       .add_certification_subkey()
1186    /// #       .add_transport_encryption_subkey()
1187    /// #       .add_transport_encryption_subkey()
1188    /// #       .add_authentication_subkey()
1189    /// #       .generate()?;
1190    /// #   let mut i = 0;
1191    /// for ka in cert.keys()
1192    ///     .with_policy(p, None)
1193    ///     .for_transport_encryption()
1194    /// {
1195    ///     // Valid encryption-capable keys for data in transit.
1196    /// #   i += 1;
1197    /// }
1198    /// # assert_eq!(i, 2);
1199    /// # Ok(()) }
1200    /// ```
1201    ///
1202    ///   [`ValidKeyAmalgamation::for_transport_encryption`]: ValidKeyAmalgamation::for_transport_encryption()
1203    pub fn for_transport_encryption(self) -> Self {
1204        self.key_flags(KeyFlags::empty().set_transport_encryption())
1205    }
1206
1207    /// Returns keys that are alive.
1208    ///
1209    /// A `ValidKeyAmalgamation` is guaranteed to have a live *binding
1210    /// signature*.  This is independent of whether the *key* is live,
1211    /// or the *certificate* is live, i.e., if you care about those
1212    /// things, you need to check them too.
1213    ///
1214    /// For a definition of liveness, see the [`key_alive`] method.
1215    ///
1216    /// # Examples
1217    ///
1218    /// ```
1219    /// # use sequoia_openpgp as openpgp;
1220    /// # use openpgp::cert::prelude::*;
1221    /// use openpgp::policy::StandardPolicy;
1222    ///
1223    /// # fn main() -> openpgp::Result<()> {
1224    /// let p = &StandardPolicy::new();
1225    ///
1226    /// #   let (cert, _) = CertBuilder::new()
1227    /// #       .add_authentication_subkey()
1228    /// #       .add_certification_subkey()
1229    /// #       .add_transport_encryption_subkey()
1230    /// #       .add_transport_encryption_subkey()
1231    /// #       .add_authentication_subkey()
1232    /// #       .generate()?;
1233    /// for ka in cert.keys()
1234    ///     .with_policy(p, None)
1235    ///     .alive()
1236    /// {
1237    ///     // ka is alive.
1238    /// }
1239    /// # Ok(()) }
1240    /// ```
1241    ///
1242    /// [`key_alive`]: crate::packet::signature::subpacket::SubpacketAreas::key_alive()
1243    pub fn alive(mut self) -> Self
1244    {
1245        self.alive = Some(());
1246        self
1247    }
1248
1249    /// Returns keys based on their revocation status.
1250    ///
1251    /// A value of `None` disables this filter.
1252    ///
1253    /// If you call this function multiple times on the same
1254    /// `ValidKeyAmalgamationIter`, only the last value is used.
1255    ///
1256    /// This filter checks the key's revocation status; it does
1257    /// not check the certificate's revocation status.
1258    ///
1259    /// This filter only checks whether the key has no valid-self
1260    /// revocations at the specified time.  It does not check
1261    /// third-party revocations.
1262    ///
1263    /// # Examples
1264    ///
1265    /// ```
1266    /// # use sequoia_openpgp as openpgp;
1267    /// # use openpgp::cert::prelude::*;
1268    /// use openpgp::policy::StandardPolicy;
1269    ///
1270    /// # fn main() -> openpgp::Result<()> {
1271    /// let p = &StandardPolicy::new();
1272    ///
1273    /// #   let (cert, _) = CertBuilder::new()
1274    /// #       .add_authentication_subkey()
1275    /// #       .add_certification_subkey()
1276    /// #       .add_transport_encryption_subkey()
1277    /// #       .add_transport_encryption_subkey()
1278    /// #       .add_authentication_subkey()
1279    /// #       .generate()?;
1280    /// for ka in cert.keys()
1281    ///     .with_policy(p, None)
1282    ///     .revoked(false)
1283    /// {
1284    ///     // ka has no self-revocations; recall: this filter doesn't check
1285    ///     // third-party revocations.
1286    /// }
1287    /// # Ok(()) }
1288    /// ```
1289    ///
1290    /// This filter checks whether a key's revocation status is
1291    /// `RevocationStatus::Revoked` or not.
1292    /// `ValidKeyAmalgamationIter::revoked(false)` is equivalent to:
1293    ///
1294    /// ```rust
1295    /// # use sequoia_openpgp as openpgp;
1296    /// # use openpgp::Result;
1297    /// use openpgp::types::RevocationStatus;
1298    /// # use openpgp::cert::prelude::*;
1299    /// use openpgp::policy::StandardPolicy;
1300    ///
1301    /// # fn main() -> Result<()> {
1302    /// #     let (cert, _) =
1303    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
1304    /// #         .generate()?;
1305    /// let p = &StandardPolicy::new();
1306    ///
1307    /// # let timestamp = None;
1308    /// let non_revoked_keys = cert
1309    ///     .keys()
1310    ///     .with_policy(p, timestamp)
1311    ///     .filter(|ka| {
1312    ///         match ka.revocation_status() {
1313    ///             RevocationStatus::Revoked(_) =>
1314    ///                 // It's definitely revoked, skip it.
1315    ///                 false,
1316    ///             RevocationStatus::CouldBe(_) =>
1317    ///                 // There is a designated revoker that we
1318    ///                 // could check, but don't (or can't).  To
1319    ///                 // avoid a denial-of-service attack arising from
1320    ///                 // fake revocations, we assume that the key has
1321    ///                 // not been revoked and return it.
1322    ///                 true,
1323    ///             RevocationStatus::NotAsFarAsWeKnow =>
1324    ///                 // We have no evidence to suggest that the key
1325    ///                 // is revoked.
1326    ///                 true,
1327    ///         }
1328    ///     })
1329    ///     .map(|ka| ka.key())
1330    ///     .collect::<Vec<_>>();
1331    /// #     Ok(())
1332    /// # }
1333    /// ```
1334    ///
1335    /// As the example shows, this filter is significantly less
1336    /// flexible than using `KeyAmalgamation::revocation_status`.
1337    /// However, this filter implements a typical policy, and does not
1338    /// preclude using something like `Iter::filter` to implement
1339    /// alternative policies.
1340    pub fn revoked<T>(mut self, revoked: T) -> Self
1341        where T: Into<Option<bool>>
1342    {
1343        self.revoked = revoked.into();
1344        self
1345    }
1346
1347    /// Changes the iterator to only return keys with secret key
1348    /// material.
1349    ///
1350    /// # Examples
1351    ///
1352    /// ```rust
1353    /// # use sequoia_openpgp as openpgp;
1354    /// # use openpgp::Result;
1355    /// # use openpgp::cert::prelude::*;
1356    /// use openpgp::policy::StandardPolicy;
1357    ///
1358    /// # fn main() -> Result<()> {
1359    /// let p = &StandardPolicy::new();
1360    ///
1361    /// #     let (cert, _) =
1362    /// #         CertBuilder::new().set_password(Some("password".into()))
1363    /// #         .generate()?;
1364    /// for ka in cert.keys().with_policy(p, None).secret() {
1365    ///     // Use it.
1366    /// }
1367    /// #     assert!(cert.keys().with_policy(p, None).secret().count() == 1);
1368    /// #
1369    /// #     let (cert, _) = CertBuilder::new().generate()?;
1370    /// #     assert!(cert.keys().with_policy(p, None).secret().count() == 1);
1371    /// #     Ok(())
1372    /// # }
1373    /// ```
1374    pub fn secret(self) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1375        ValidKeyAmalgamationIter {
1376            cert: self.cert,
1377            primary: self.primary,
1378            subkey_iter: self.subkey_iter,
1379
1380            time: self.time,
1381            policy: self.policy,
1382
1383            // The filters.
1384            encrypted_secret: Some(true),
1385            unencrypted_secret: Some(true),
1386            key_handles: self.key_handles,
1387            supported: self.supported,
1388            flags: self.flags,
1389            alive: self.alive,
1390            revoked: self.revoked,
1391
1392            _p: std::marker::PhantomData,
1393            _r: std::marker::PhantomData,
1394        }
1395    }
1396
1397    /// Changes the iterator to only return keys with encrypted secret key
1398    /// material.
1399    ///
1400    /// # Examples
1401    ///
1402    /// ```rust
1403    /// # use sequoia_openpgp as openpgp;
1404    /// # use openpgp::Result;
1405    /// # use openpgp::cert::prelude::*;
1406    /// use openpgp::policy::StandardPolicy;
1407    ///
1408    /// # fn main() -> Result<()> {
1409    /// let p = &StandardPolicy::new();
1410    ///
1411    /// #     let (cert, _) =
1412    /// #         CertBuilder::new().set_password(Some("password".into()))
1413    /// #         .generate()?;
1414    /// for ka in cert.keys().with_policy(p, None).encrypted_secret() {
1415    ///     // Use it.
1416    /// }
1417    /// #     assert!(cert.keys().with_policy(p, None).encrypted_secret().count() == 1);
1418    /// #     Ok(())
1419    /// # }
1420    /// ```
1421    pub fn encrypted_secret(
1422        self,
1423    ) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1424        ValidKeyAmalgamationIter {
1425            cert: self.cert,
1426            primary: self.primary,
1427            subkey_iter: self.subkey_iter,
1428
1429            time: self.time,
1430            policy: self.policy,
1431
1432            // The filters.
1433            encrypted_secret: Some(true),
1434            unencrypted_secret: self.unencrypted_secret,
1435            key_handles: self.key_handles,
1436            supported: self.supported,
1437            flags: self.flags,
1438            alive: self.alive,
1439            revoked: self.revoked,
1440
1441            _p: std::marker::PhantomData,
1442            _r: std::marker::PhantomData,
1443        }
1444    }
1445
1446    /// Changes the iterator to only return keys with unencrypted
1447    /// secret key material.
1448    ///
1449    /// # Examples
1450    ///
1451    /// ```rust
1452    /// # use sequoia_openpgp as openpgp;
1453    /// # use openpgp::Result;
1454    /// # use openpgp::cert::prelude::*;
1455    /// use openpgp::policy::StandardPolicy;
1456    ///
1457    /// # fn main() -> Result<()> {
1458    /// let p = &StandardPolicy::new();
1459    ///
1460    /// #     let (cert, _) = CertBuilder::new().generate()?;
1461    /// for ka in cert.keys().with_policy(p, None).unencrypted_secret() {
1462    ///     // Use it.
1463    /// }
1464    /// #     assert!(cert.keys().with_policy(p, None).unencrypted_secret().count() == 1);
1465    /// #     Ok(())
1466    /// # }
1467    /// ```
1468    pub fn unencrypted_secret(self) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1469        ValidKeyAmalgamationIter {
1470            cert: self.cert,
1471            primary: self.primary,
1472            subkey_iter: self.subkey_iter,
1473
1474            time: self.time,
1475            policy: self.policy,
1476
1477            // The filters.
1478            encrypted_secret: self.encrypted_secret,
1479            unencrypted_secret: Some(true),
1480            key_handles: self.key_handles,
1481            supported: self.supported,
1482            flags: self.flags,
1483            alive: self.alive,
1484            revoked: self.revoked,
1485
1486            _p: std::marker::PhantomData,
1487            _r: std::marker::PhantomData,
1488        }
1489    }
1490
1491    /// Changes the iterator to only return a key if it matches one of
1492    /// the specified `KeyHandle`s.
1493    ///
1494    /// This function is cumulative.  If you call this function (or
1495    /// [`key_handles`]) multiple times, then the iterator returns a
1496    /// key if it matches *any* of the specified [`KeyHandle`s].
1497    ///
1498    /// This function uses [`KeyHandle::aliases`] to compare key
1499    /// handles.
1500    ///
1501    /// # Examples
1502    ///
1503    /// ```rust
1504    /// # use sequoia_openpgp as openpgp;
1505    /// # use openpgp::Result;
1506    /// # use openpgp::cert::prelude::*;
1507    /// use openpgp::policy::StandardPolicy;
1508    ///
1509    /// # fn main() -> Result<()> {
1510    /// let p = &StandardPolicy::new();
1511    ///
1512    /// #     let (cert, _) =
1513    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
1514    /// #         .generate()?;
1515    /// # let key_handle = cert.primary_key().key().key_handle();
1516    /// # let mut i = 0;
1517    /// for ka in cert.keys().with_policy(p, None).key_handle(key_handle) {
1518    ///     // Use it.
1519    /// #   i += 1;
1520    /// }
1521    /// # assert_eq!(i, 1);
1522    /// #     Ok(())
1523    /// # }
1524    /// ```
1525    ///
1526    /// [`KeyHandle`s]: super::super::super::KeyHandle
1527    /// [`key_handles`]: ValidKeyAmalgamationIter::key_handles()
1528    /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
1529    pub fn key_handle<H>(mut self, h: H) -> Self
1530        where H: Into<KeyHandle>
1531    {
1532        self.key_handles.push(h.into());
1533        self
1534    }
1535
1536    /// Changes the iterator to only return a key if it matches one of
1537    /// the specified `KeyHandle`s.
1538    ///
1539    /// If the given `handles` iterator is empty, the set of returned
1540    /// keys is not constrained.
1541    ///
1542    /// This function is cumulative.  If you call this function (or
1543    /// [`key_handle`]) multiple times, then the iterator returns a key
1544    /// if it matches *any* of the specified [`KeyHandle`s].
1545    ///
1546    /// This function uses [`KeyHandle::aliases`] to compare key
1547    /// handles.
1548    ///
1549    /// # Examples
1550    ///
1551    /// ```rust
1552    /// # use sequoia_openpgp as openpgp;
1553    /// # use openpgp::Result;
1554    /// # use openpgp::cert::prelude::*;
1555    /// use openpgp::policy::StandardPolicy;
1556    ///
1557    /// # fn main() -> Result<()> {
1558    /// let p = &StandardPolicy::new();
1559    ///
1560    /// #     let (cert, _) =
1561    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
1562    /// #         .generate()?;
1563    /// # let key_handles = &[cert.primary_key().key().key_handle()][..];
1564    /// # let mut i = 0;
1565    /// for ka in cert.keys().with_policy(p, None).key_handles(key_handles) {
1566    ///     // Use it.
1567    /// #   i += 1;
1568    /// }
1569    /// # assert_eq!(i, 1);
1570    /// #     Ok(())
1571    /// # }
1572    /// ```
1573    ///
1574    /// [`KeyHandle`s]: super::super::super::KeyHandle
1575    /// [`key_handle`]: KeyAmalgamationIter::key_handle()
1576    /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
1577    pub fn key_handles<H, K>(mut self, handles: H) -> Self
1578    where
1579        H: IntoIterator<Item=K>,
1580        K: Borrow<KeyHandle>,
1581    {
1582        let mut handles = handles.into_iter()
1583            .map(|h| h.borrow().clone())
1584            .collect::<Vec<_>>();
1585
1586        self.key_handles.append(&mut handles);
1587        self
1588    }
1589
1590    /// Changes the iterator to only return a key if it is supported
1591    /// by Sequoia's cryptographic backend.
1592    ///
1593    /// Which public key encryption algorithms Sequoia supports
1594    /// depends on the cryptographic backend selected at compile time.
1595    /// This filter makes sure that only supported keys are returned.
1596    ///
1597    /// # Examples
1598    ///
1599    /// ```rust
1600    /// # fn main() -> sequoia_openpgp::Result<()> {
1601    /// # use sequoia_openpgp as openpgp;
1602    /// # use openpgp::cert::prelude::*;
1603    /// #     let (cert, _) =
1604    /// #         CertBuilder::general_purpose(Some("alice@example.org"))
1605    /// #         .generate()?;
1606    /// # let mut i = 0;
1607    /// use openpgp::policy::StandardPolicy;
1608    ///
1609    /// let p = &StandardPolicy::new();
1610    ///
1611    /// for ka in cert.keys().with_policy(p, None).supported() {
1612    ///     // Use it.
1613    /// #   i += 1;
1614    /// }
1615    /// # assert_eq!(i, 3);
1616    /// # Ok(()) }
1617    /// ```
1618    pub fn supported(mut self) -> Self {
1619        self.supported = Some(true);
1620        self
1621    }
1622
1623    /// Changes the iterator to skip the primary key.
1624    ///
1625    /// This also changes the iterator's return type.  Instead of
1626    /// returning a [`ValidErasedKeyAmalgamation`], it returns a
1627    /// [`ValidSubordinateKeyAmalgamation`].
1628    ///
1629    /// # Examples
1630    ///
1631    /// ```
1632    /// # use sequoia_openpgp as openpgp;
1633    /// # use openpgp::cert::prelude::*;
1634    /// use openpgp::policy::StandardPolicy;
1635    ///
1636    /// # fn main() -> openpgp::Result<()> {
1637    /// let p = &StandardPolicy::new();
1638    ///
1639    /// #   let (cert, _) = CertBuilder::new()
1640    /// #       .add_signing_subkey()
1641    /// #       .add_certification_subkey()
1642    /// #       .add_transport_encryption_subkey()
1643    /// #       .add_storage_encryption_subkey()
1644    /// #       .add_authentication_subkey()
1645    /// #       .generate()?;
1646    /// #   let mut i = 0;
1647    /// for ka in cert.keys().with_policy(p, None).subkeys() {
1648    ///     assert!(! ka.primary());
1649    /// #   i += 1;
1650    /// }
1651    /// # assert_eq!(cert.keys().count(), 6);
1652    /// # assert_eq!(i, 5);
1653    /// # Ok(()) }
1654    /// ```
1655    ///
1656    pub fn subkeys(self) -> ValidKeyAmalgamationIter<'a, P, key::SubordinateRole> {
1657        ValidKeyAmalgamationIter {
1658            cert: self.cert,
1659            primary: true,
1660            subkey_iter: self.subkey_iter,
1661
1662            time: self.time,
1663            policy: self.policy,
1664
1665            // The filters.
1666            encrypted_secret: self.encrypted_secret,
1667            unencrypted_secret: self.unencrypted_secret,
1668            key_handles: self.key_handles,
1669            supported: self.supported,
1670            flags: self.flags,
1671            alive: self.alive,
1672            revoked: self.revoked,
1673
1674            _p: std::marker::PhantomData,
1675            _r: std::marker::PhantomData,
1676        }
1677    }
1678}
1679
1680#[cfg(test)]
1681mod test {
1682    use super::*;
1683    use crate::{
1684        parse::Parse,
1685        cert::builder::CertBuilder,
1686    };
1687    use crate::policy::StandardPolicy as P;
1688
1689    #[test]
1690    fn key_iter_test() {
1691        let key = Cert::from_bytes(crate::tests::key("neal.pgp")).unwrap();
1692        assert_eq!(1 + key.subkeys().count(),
1693                   key.keys().count());
1694    }
1695
1696    #[test]
1697    fn select_no_keys() {
1698        let p = &P::new();
1699        let (cert, _) = CertBuilder::new()
1700            .generate().unwrap();
1701        let flags = KeyFlags::empty().set_transport_encryption();
1702
1703        assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 0);
1704    }
1705
1706    #[test]
1707    fn select_valid_and_right_flags() {
1708        let p = &P::new();
1709        let (cert, _) = CertBuilder::new()
1710            .add_transport_encryption_subkey()
1711            .generate().unwrap();
1712        let flags = KeyFlags::empty().set_transport_encryption();
1713
1714        assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
1715    }
1716
1717    #[test]
1718    fn select_valid_and_wrong_flags() {
1719        let p = &P::new();
1720        let (cert, _) = CertBuilder::new()
1721            .add_transport_encryption_subkey()
1722            .add_signing_subkey()
1723            .generate().unwrap();
1724        let flags = KeyFlags::empty().set_transport_encryption();
1725
1726        assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
1727    }
1728
1729    #[test]
1730    fn select_invalid_and_right_flags() {
1731        let p = &P::new();
1732        let (cert, _) = CertBuilder::new()
1733            .add_transport_encryption_subkey()
1734            .generate().unwrap();
1735        let flags = KeyFlags::empty().set_transport_encryption();
1736
1737        let now = crate::now()
1738            - std::time::Duration::new(52 * 7 * 24 * 60 * 60, 0);
1739        assert_eq!(cert.keys().with_policy(p, now).key_flags(flags).alive().count(),
1740                   0);
1741    }
1742
1743    #[test]
1744    fn select_primary() {
1745        let p = &P::new();
1746        let (cert, _) = CertBuilder::new()
1747            .add_certification_subkey()
1748            .generate().unwrap();
1749        let flags = KeyFlags::empty().set_certification();
1750
1751        assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(),
1752                   2);
1753    }
1754
1755    #[test]
1756    fn selectors() {
1757        let p = &P::new();
1758        let (cert, _) = CertBuilder::new()
1759            .add_signing_subkey()
1760            .add_certification_subkey()
1761            .add_transport_encryption_subkey()
1762            .add_storage_encryption_subkey()
1763            .add_authentication_subkey()
1764            .generate().unwrap();
1765        assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1766                       .for_certification().count(),
1767                   2);
1768        assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1769                       .for_transport_encryption().count(),
1770                   1);
1771        assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1772                       .for_storage_encryption().count(),
1773                   1);
1774
1775        assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1776                       .for_signing().count(),
1777                   1);
1778        assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1779                       .key_flags(KeyFlags::empty().set_authentication())
1780                       .count(),
1781                   1);
1782    }
1783
1784    #[test]
1785    fn select_key_handle() {
1786        let p = &P::new();
1787
1788        let (cert, _) = CertBuilder::new()
1789            .add_signing_subkey()
1790            .add_certification_subkey()
1791            .add_transport_encryption_subkey()
1792            .add_storage_encryption_subkey()
1793            .add_authentication_subkey()
1794            .generate().unwrap();
1795
1796        let keys = cert.keys().count();
1797        assert_eq!(keys, 6);
1798
1799        let keyids = cert.keys().map(|ka| ka.key().keyid()).collect::<Vec<_>>();
1800
1801        fn check(got: &[KeyHandle], expected: &[KeyHandle]) {
1802            if expected.len() != got.len() {
1803                panic!("Got {}, expected {} handles",
1804                       got.len(), expected.len());
1805            }
1806
1807            for (g, e) in got.iter().zip(expected.iter()) {
1808                if !e.aliases(g) {
1809                    panic!("     Got: {:?}\nExpected: {:?}",
1810                           got, expected);
1811                }
1812            }
1813        }
1814
1815        for i in 1..keys {
1816            for keyids in keyids[..].windows(i) {
1817                let keyids : Vec<KeyHandle>
1818                    = keyids.iter().map(Into::into).collect();
1819                assert_eq!(keyids.len(), i);
1820
1821                check(
1822                    &cert.keys().key_handles(keyids.iter())
1823                        .map(|ka| ka.key().key_handle())
1824                        .collect::<Vec<KeyHandle>>(),
1825                    &keyids);
1826                check(
1827                    &cert.keys().with_policy(p, None).key_handles(keyids.iter())
1828                        .map(|ka| ka.key().key_handle())
1829                        .collect::<Vec<KeyHandle>>(),
1830                    &keyids);
1831                check(
1832                    &cert.keys().key_handles(keyids.iter()).with_policy(p, None)
1833                        .map(|ka| ka.key().key_handle())
1834                        .collect::<Vec<KeyHandle>>(),
1835                    &keyids);
1836            }
1837        }
1838    }
1839
1840    #[test]
1841    #[allow(deprecated)]
1842    fn select_supported() -> crate::Result<()> {
1843        use crate::types::PublicKeyAlgorithm;
1844        if ! PublicKeyAlgorithm::DSA.is_supported()
1845            || PublicKeyAlgorithm::ElGamalEncrypt.is_supported()
1846        {
1847            return Ok(()); // Skip on this backend.
1848        }
1849
1850        let cert =
1851            Cert::from_bytes(crate::tests::key("dsa2048-elgamal3072.pgp"))?;
1852        assert_eq!(cert.keys().count(), 2);
1853        assert_eq!(cert.keys().supported().count(), 1);
1854        let p = unsafe { &crate::policy::NullPolicy::new() };
1855        assert_eq!(cert.keys().with_policy(p, None).count(), 2);
1856        assert_eq!(cert.keys().with_policy(p, None).supported().count(), 1);
1857        Ok(())
1858    }
1859}