tor_keymgr/
mgr.rs

1//! Code for managing multiple [`Keystore`](crate::Keystore)s.
2//!
3//! See the [`KeyMgr`] docs for more details.
4
5use crate::raw::{RawEntryId, RawKeystoreEntry};
6use crate::{
7    ArtiPath, BoxedKeystore, KeyCertificateSpecifier, KeyPath, KeyPathError, KeyPathInfo,
8    KeyPathInfoExtractor, KeyPathPattern, KeySpecifier, KeystoreCorruptionError,
9    KeystoreEntryResult, KeystoreId, KeystoreSelector, Result,
10};
11
12use itertools::Itertools;
13use std::iter;
14use std::result::Result as StdResult;
15use tor_error::{bad_api_usage, internal, into_bad_api_usage};
16use tor_key_forge::{
17    ItemType, Keygen, KeygenRng, KeystoreItemType, ToEncodableCert, ToEncodableKey,
18};
19
20/// A key manager that acts as a frontend to a primary [`Keystore`](crate::Keystore) and
21/// any number of secondary [`Keystore`](crate::Keystore)s.
22///
23/// Note: [`KeyMgr`] is a low-level utility and does not implement caching (the key stores are
24/// accessed for every read/write).
25///
26/// The `KeyMgr` accessors - currently just [`get()`](KeyMgr::get) -
27/// search the configured key stores in order: first the primary key store,
28/// and then the secondary stores, in order.
29///
30///
31/// ## Concurrent key store access
32///
33/// The key stores will allow concurrent modification by different processes. In
34/// order to implement this safely without locking, the key store operations (get,
35/// insert, remove) will need to be atomic.
36///
37/// **Note**: [`KeyMgr::generate`] and [`KeyMgr::get_or_generate`] should **not** be used
38/// concurrently with any other `KeyMgr` operation that mutates the same key
39/// (i.e. a key with the same `ArtiPath`), because
40/// their outcome depends on whether the selected key store
41/// [`contains`][crate::Keystore::contains]
42/// the specified key (and thus suffers from a TOCTOU race).
43#[derive(derive_builder::Builder)]
44#[builder(pattern = "owned", build_fn(private, name = "build_unvalidated"))]
45pub struct KeyMgr {
46    /// The primary key store.
47    primary_store: BoxedKeystore,
48    /// The secondary key stores.
49    #[builder(default, setter(custom))]
50    secondary_stores: Vec<BoxedKeystore>,
51    /// The key info extractors.
52    ///
53    /// These are initialized internally by [`KeyMgrBuilder::build`], using the values collected
54    /// using `inventory`.
55    #[builder(default, setter(skip))]
56    key_info_extractors: Vec<&'static dyn KeyPathInfoExtractor>,
57}
58
59/// A keystore entry descriptor.
60///
61/// This identifies a key entry from a specific keystore.
62/// The key entry can be retrieved, using [`KeyMgr::get_entry`],
63/// or removed, using [`KeyMgr::remove_entry`].
64///
65/// Returned from [`KeyMgr::list_matching`].
66#[derive(Clone, Debug, PartialEq, amplify::Getters)]
67pub struct KeystoreEntry<'a> {
68    /// The [`KeyPath`] of the key.
69    key_path: KeyPath,
70    /// The [`KeystoreItemType`] of the key.
71    key_type: KeystoreItemType,
72    /// The [`KeystoreId`] of the keystore where the key was found.
73    #[getter(as_copy)]
74    keystore_id: &'a KeystoreId,
75    /// The [`RawEntryId`] of the key, an identifier used in
76    /// `arti raw` operations.
77    #[getter(skip)]
78    raw_id: RawEntryId,
79}
80
81impl<'a> KeystoreEntry<'a> {
82    /// Create a new `KeystoreEntry`
83    pub(crate) fn new(
84        key_path: KeyPath,
85        key_type: KeystoreItemType,
86        keystore_id: &'a KeystoreId,
87        raw_id: RawEntryId,
88    ) -> Self {
89        Self {
90            key_path,
91            key_type,
92            keystore_id,
93            raw_id,
94        }
95    }
96
97    /// Return an instance of [`RawKeystoreEntry`]
98    #[cfg(feature = "onion-service-cli-extra")]
99    #[cfg_attr(docsrs, doc(cfg(feature = "onion-service-cli-extra")))]
100    pub fn raw_entry(&self) -> RawKeystoreEntry {
101        RawKeystoreEntry::new(self.raw_id.clone(), self.keystore_id.clone())
102    }
103}
104
105// NOTE: Some methods require a `KeystoreEntryResult<KeystoreEntry>` as an
106// argument (e.g.: `KeyMgr::raw_keystore_entry`). For this reason  implementing
107// `From<KeystoreEntry<'a>> for KeystoreEntryResult<KeystoreEntry<'a>>` makes
108// `KeystoreEntry` more ergonomic.
109impl<'a> From<KeystoreEntry<'a>> for KeystoreEntryResult<KeystoreEntry<'a>> {
110    fn from(val: KeystoreEntry<'a>) -> Self {
111        Ok(val)
112    }
113}
114
115impl KeyMgrBuilder {
116    /// Construct a [`KeyMgr`] from this builder.
117    pub fn build(self) -> StdResult<KeyMgr, KeyMgrBuilderError> {
118        use itertools::Itertools as _;
119
120        let mut keymgr = self.build_unvalidated()?;
121
122        if !keymgr.all_stores().map(|s| s.id()).all_unique() {
123            return Err(KeyMgrBuilderError::ValidationError(
124                "the keystore IDs are not pairwise unique".into(),
125            ));
126        }
127
128        keymgr.key_info_extractors = inventory::iter::<&'static dyn KeyPathInfoExtractor>
129            .into_iter()
130            .copied()
131            .collect();
132
133        Ok(keymgr)
134    }
135}
136
137// TODO: auto-generate using define_list_builder_accessors/define_list_builder_helper
138// when that becomes possible.
139//
140// See https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/1760#note_2969841
141impl KeyMgrBuilder {
142    /// Access the being-built list of secondary stores (resolving default)
143    ///
144    /// If the field has not yet been set or accessed, the default list will be
145    /// constructed and a mutable reference to the now-defaulted list of builders
146    /// will be returned.
147    pub fn secondary_stores(&mut self) -> &mut Vec<BoxedKeystore> {
148        self.secondary_stores.get_or_insert(Default::default())
149    }
150
151    /// Set the whole list (overriding the default)
152    pub fn set_secondary_stores(mut self, list: Vec<BoxedKeystore>) -> Self {
153        self.secondary_stores = Some(list);
154        self
155    }
156
157    /// Inspect the being-built list (with default unresolved)
158    ///
159    /// If the list has not yet been set, or accessed, `&None` is returned.
160    pub fn opt_secondary_stores(&self) -> &Option<Vec<BoxedKeystore>> {
161        &self.secondary_stores
162    }
163
164    /// Mutably access the being-built list (with default unresolved)
165    ///
166    /// If the list has not yet been set, or accessed, `&mut None` is returned.
167    pub fn opt_secondary_stores_mut(&mut self) -> &mut Option<Vec<BoxedKeystore>> {
168        &mut self.secondary_stores
169    }
170}
171
172inventory::collect!(&'static dyn crate::KeyPathInfoExtractor);
173
174impl KeyMgr {
175    /// Read a key from one of the key stores, and try to deserialize it as `K::Key`.
176    ///
177    /// The key returned is retrieved from the first key store that contains an entry for the given
178    /// specifier.
179    ///
180    /// Returns `Ok(None)` if none of the key stores have the requested key.
181    pub fn get<K: ToEncodableKey>(&self, key_spec: &dyn KeySpecifier) -> Result<Option<K>> {
182        let result = self.get_from_store(key_spec, &K::Key::item_type(), self.all_stores())?;
183        if result.is_none() {
184            // If the key_spec is the specifier for the public part of a keypair,
185            // try getting the pair and extracting the public portion from it.
186            if let Some(key_pair_spec) = key_spec.keypair_specifier() {
187                return Ok(self.get::<K::KeyPair>(&*key_pair_spec)?.map(|k| k.into()));
188            }
189        }
190        Ok(result)
191    }
192
193    /// Retrieve the specified keystore entry, and try to deserialize it as `K::Key`.
194    ///
195    /// The key returned is retrieved from the key store specified in the [`KeystoreEntry`].
196    ///
197    /// Returns `Ok(None)` if the key store does not contain the requested entry.
198    ///
199    /// Returns an error if the specified `key_type` does not match `K::Key::item_type()`.
200    pub fn get_entry<K: ToEncodableKey>(&self, entry: &KeystoreEntry) -> Result<Option<K>> {
201        let selector = entry.keystore_id().into();
202        let store = self.select_keystore(&selector)?;
203        self.get_from_store(entry.key_path(), entry.key_type(), [store].into_iter())
204    }
205
206    /// Read the key identified by `key_spec`.
207    ///
208    /// The key returned is retrieved from the first key store that contains an entry for the given
209    /// specifier.
210    ///
211    /// If the requested key does not exist in any of the key stores, this generates a new key of
212    /// type `K` from the key created using using `K::Key`'s [`Keygen`] implementation, and inserts
213    /// it into the specified keystore, returning the newly inserted value.
214    ///
215    /// This is a convenience wrapper around [`get()`](KeyMgr::get) and
216    /// [`generate()`](KeyMgr::generate).
217    pub fn get_or_generate<K>(
218        &self,
219        key_spec: &dyn KeySpecifier,
220        selector: KeystoreSelector,
221        rng: &mut dyn KeygenRng,
222    ) -> Result<K>
223    where
224        K: ToEncodableKey,
225        K::Key: Keygen,
226    {
227        match self.get(key_spec)? {
228            Some(k) => Ok(k),
229            None => self.generate(key_spec, selector, rng, false),
230        }
231    }
232
233    /// Generate a new key of type `K`, and insert it into the key store specified by `selector`.
234    ///
235    /// If the key already exists in the specified key store, the `overwrite` flag is used to
236    /// decide whether to overwrite it with a newly generated key.
237    ///
238    /// On success, this function returns the newly generated key.
239    ///
240    /// Returns [`Error::KeyAlreadyExists`](crate::Error::KeyAlreadyExists)
241    /// if the key already exists in the specified key store and `overwrite` is `false`.
242    ///
243    /// **IMPORTANT**: using this function concurrently with any other `KeyMgr` operation that
244    /// mutates the key store state is **not** recommended, as it can yield surprising results! The
245    /// outcome of [`KeyMgr::generate`] depends on whether the selected key store
246    /// [`contains`][crate::Keystore::contains] the specified key, and thus suffers from a TOCTOU race.
247    //
248    // TODO (#1119): can we make this less racy without a lock? Perhaps we should say we'll always
249    // overwrite any existing keys.
250    //
251    // TODO: consider replacing the overwrite boolean with a GenerateOptions type
252    // (sort of like std::fs::OpenOptions)
253    pub fn generate<K>(
254        &self,
255        key_spec: &dyn KeySpecifier,
256        selector: KeystoreSelector,
257        rng: &mut dyn KeygenRng,
258        overwrite: bool,
259    ) -> Result<K>
260    where
261        K: ToEncodableKey,
262        K::Key: Keygen,
263    {
264        let store = self.select_keystore(&selector)?;
265
266        if overwrite || !store.contains(key_spec, &K::Key::item_type())? {
267            let key = K::Key::generate(rng)?;
268            store.insert(&key, key_spec)?;
269
270            Ok(K::from_encodable_key(key))
271        } else {
272            Err(crate::Error::KeyAlreadyExists)
273        }
274    }
275
276    /// Insert `key` into the [`Keystore`](crate::Keystore) specified by `selector`.
277    ///
278    /// If the key already exists in the specified key store, the `overwrite` flag is used to
279    /// decide whether to overwrite it with the provided key.
280    ///
281    /// If this key is not already in the keystore, `None` is returned.
282    ///
283    /// If this key already exists in the keystore, its value is updated
284    /// and the old value is returned.
285    ///
286    /// Returns an error if the selected keystore is not the primary keystore or one of the
287    /// configured secondary stores.
288    pub fn insert<K: ToEncodableKey>(
289        &self,
290        key: K,
291        key_spec: &dyn KeySpecifier,
292        selector: KeystoreSelector,
293        overwrite: bool,
294    ) -> Result<Option<K>> {
295        let key = key.to_encodable_key();
296        let store = self.select_keystore(&selector)?;
297        let key_type = K::Key::item_type();
298        let old_key: Option<K> = self.get_from_store(key_spec, &key_type, [store].into_iter())?;
299
300        if old_key.is_some() && !overwrite {
301            Err(crate::Error::KeyAlreadyExists)
302        } else {
303            let () = store.insert(&key, key_spec)?;
304            Ok(old_key)
305        }
306    }
307
308    /// Remove the key identified by `key_spec` from the [`Keystore`](crate::Keystore)
309    /// specified by `selector`.
310    ///
311    /// Returns an error if the selected keystore is not the primary keystore or one of the
312    /// configured secondary stores.
313    ///
314    /// Returns the value of the removed key,
315    /// or `Ok(None)` if the key does not exist in the requested keystore.
316    ///
317    /// Returns `Err` if an error occurred while trying to remove the key.
318    pub fn remove<K: ToEncodableKey>(
319        &self,
320        key_spec: &dyn KeySpecifier,
321        selector: KeystoreSelector,
322    ) -> Result<Option<K>> {
323        let store = self.select_keystore(&selector)?;
324        let key_type = K::Key::item_type();
325        let old_key: Option<K> = self.get_from_store(key_spec, &key_type, [store].into_iter())?;
326
327        store.remove(key_spec, &key_type)?;
328
329        Ok(old_key)
330    }
331
332    /// Remove the specified keystore entry.
333    ///
334    /// Like [`KeyMgr::remove`], except this function does not return the value of the removed key.
335    ///
336    /// A return value of `Ok(None)` indicates the key was not found in the specified key store,
337    /// whereas `Ok(Some(())` means the key was successfully removed.
338    //
339    // TODO: We should be consistent and return the removed key.
340    //
341    // This probably will involve changing the return type of Keystore::remove
342    // to Result<Option<ErasedKey>>.
343    pub fn remove_entry(&self, entry: &KeystoreEntry) -> Result<Option<()>> {
344        let selector = entry.keystore_id().into();
345        let store = self.select_keystore(&selector)?;
346
347        store.remove(entry.key_path(), entry.key_type())
348    }
349
350    /// Remove the specified keystore entry.
351    ///
352    /// Similar to [`KeyMgr::remove_entry`], except this method accepts both recognized and
353    /// unrecognized entries, identified by a raw id (in the form of a `&str`) and a
354    /// [`KeystoreId`].
355    ///
356    /// Returns an error if the entry could not be removed, or if the entry doesn't exist.
357    #[cfg(feature = "onion-service-cli-extra")]
358    pub fn remove_unchecked(&self, raw_id: &str, keystore_id: &KeystoreId) -> Result<()> {
359        let selector = KeystoreSelector::from(keystore_id);
360        let store = self.select_keystore(&selector)?;
361        let raw_id = store.raw_entry_id(raw_id)?;
362        let store = self.select_keystore(&selector)?;
363        store.remove_unchecked(&raw_id)
364    }
365
366    /// Return the keystore entry descriptors of the keys matching the specified [`KeyPathPattern`].
367    ///
368    /// NOTE: This searches for matching keys in _all_ keystores.
369    ///
370    /// NOTE: This function only returns the *recognized* entries that match the provided pattern.
371    /// The unrecognized entries (i.e. those that do not have a valid [`KeyPath`]) will be filtered out,
372    /// even if they match the specified pattern.
373    pub fn list_matching(&self, pat: &KeyPathPattern) -> Result<Vec<KeystoreEntry>> {
374        self.all_stores()
375            .map(|store| -> Result<Vec<_>> {
376                Ok(store
377                    .list()?
378                    .into_iter()
379                    .filter_map(|entry| entry.ok())
380                    .filter(|entry| entry.key_path().matches(pat))
381                    .collect::<Vec<_>>())
382            })
383            .flatten_ok()
384            .collect::<Result<Vec<_>>>()
385    }
386
387    /// List keys and certificates of the specified keystore.
388    #[cfg(feature = "onion-service-cli-extra")]
389    pub fn list_by_id(&self, id: &KeystoreId) -> Result<Vec<KeystoreEntryResult<KeystoreEntry>>> {
390        self.find_keystore(id)?.list()
391    }
392
393    /// List keys and certificates of all the keystores.
394    #[cfg(feature = "onion-service-cli-extra")]
395    pub fn list(&self) -> Result<Vec<KeystoreEntryResult<KeystoreEntry>>> {
396        self.all_stores()
397            .map(|store| -> Result<Vec<_>> { store.list() })
398            .flatten_ok()
399            .collect::<Result<Vec<_>>>()
400    }
401
402    /// List keys and certificates of a specific keystore.
403    #[cfg(feature = "onion-service-cli-extra")]
404    pub fn list_keystores(&self) -> Vec<KeystoreId> {
405        self.all_stores()
406            .map(|store| store.id().to_owned())
407            .collect()
408    }
409
410    /// Describe the specified key.
411    ///
412    /// Returns [`KeyPathError::Unrecognized`] if none of the registered
413    /// [`KeyPathInfoExtractor`]s is able to parse the specified [`KeyPath`].
414    ///
415    /// This function uses the [`KeyPathInfoExtractor`]s registered using
416    /// [`register_key_info_extractor`](crate::register_key_info_extractor),
417    /// or by [`DefaultKeySpecifier`](crate::derive_deftly_template_KeySpecifier).
418    pub fn describe(&self, path: &KeyPath) -> StdResult<KeyPathInfo, KeyPathError> {
419        for info_extractor in &self.key_info_extractors {
420            if let Ok(info) = info_extractor.describe(path) {
421                return Ok(info);
422            }
423        }
424
425        Err(KeyPathError::Unrecognized(path.clone()))
426    }
427
428    /// Attempt to retrieve a key from one of the specified `stores`.
429    ///
430    /// Returns the `<K as ToEncodableKey>::Key` representation of the key.
431    ///
432    /// See [`KeyMgr::get`] for more details.
433    fn get_from_store_raw<'a, K: ItemType>(
434        &self,
435        key_spec: &dyn KeySpecifier,
436        key_type: &KeystoreItemType,
437        stores: impl Iterator<Item = &'a BoxedKeystore>,
438    ) -> Result<Option<K>> {
439        let static_key_type = K::item_type();
440        if key_type != &static_key_type {
441            return Err(internal!(
442                "key type {:?} does not match the key type {:?} of requested key K::Key",
443                key_type,
444                static_key_type
445            )
446            .into());
447        }
448
449        for store in stores {
450            let key = match store.get(key_spec, &K::item_type()) {
451                Ok(None) => {
452                    // The key doesn't exist in this store, so we check the next one...
453                    continue;
454                }
455                Ok(Some(k)) => k,
456                Err(e) => {
457                    // Note: we immediately return if one of the keystores is inaccessible.
458                    return Err(e);
459                }
460            };
461
462            // Found it! Now try to downcast it to the right type (this should _not_ fail)...
463            let key: K = key
464                .downcast::<K>()
465                .map(|k| *k)
466                .map_err(|_| internal!("failed to downcast key to requested type"))?;
467
468            return Ok(Some(key));
469        }
470
471        Ok(None)
472    }
473
474    /// Attempt to retrieve a key from one of the specified `stores`.
475    ///
476    /// See [`KeyMgr::get`] for more details.
477    fn get_from_store<'a, K: ToEncodableKey>(
478        &self,
479        key_spec: &dyn KeySpecifier,
480        key_type: &KeystoreItemType,
481        stores: impl Iterator<Item = &'a BoxedKeystore>,
482    ) -> Result<Option<K>> {
483        let Some(key) = self.get_from_store_raw::<K::Key>(key_spec, key_type, stores)? else {
484            return Ok(None);
485        };
486
487        Ok(Some(K::from_encodable_key(key)))
488    }
489
490    /// Read the specified key and certificate from one of the key stores,
491    /// deserializing the subject key as `K::Key`, the cert as `C::Cert`,
492    /// and the signing key as `C::SigningKey`.
493    ///
494    /// Returns `Ok(None)` if none of the key stores have the requested key.
495    ///
496    // Note: the behavior of this function is a bit inconsistent with
497    // get_or_generate_key_and_cert: here, if the cert is absent but
498    // its subject key is not, we return Ok(None).
499    // In get_or_generate_key_and_cert, OTOH< we return an error in that case
500    // (because we can't possibly generate the missing subject key
501    // without overwriting the cert of the missing key).
502    ///
503    /// This function validates the certificate using [`ToEncodableCert::validate`],
504    /// returning an error if it is invalid or missing.
505    #[cfg(feature = "experimental-api")]
506    pub fn get_key_and_cert<K, C>(
507        &self,
508        spec: &dyn KeyCertificateSpecifier,
509    ) -> Result<Option<(K, C)>>
510    where
511        K: ToEncodableKey,
512        C: ToEncodableCert<K>,
513    {
514        let subject_key_spec = spec.subject_key_specifier();
515        // Get the subject key...
516        let Some(key) =
517            self.get_from_store::<K>(subject_key_spec, &K::Key::item_type(), self.all_stores())?
518        else {
519            return Ok(None);
520        };
521
522        let subject_key_arti_path = subject_key_spec
523            .arti_path()
524            .map_err(|_| bad_api_usage!("subject key does not have an ArtiPath?!"))?;
525        let cert_spec =
526            ArtiPath::from_path_and_denotators(subject_key_arti_path, &spec.cert_denotators())
527                .map_err(into_bad_api_usage!("invalid certificate specifier"))?;
528
529        let Some(cert) = self.get_from_store_raw::<C::ParsedCert>(
530            &cert_spec,
531            &<C::ParsedCert as ItemType>::item_type(),
532            self.all_stores(),
533        )?
534        else {
535            return Err(KeystoreCorruptionError::MissingCertificate.into());
536        };
537
538        // Finally, get the signing key and validate the cert
539        let signed_with = self.get_cert_signing_key::<K, C>(spec)?;
540        let cert = C::validate(cert, &key, &signed_with)?;
541
542        Ok(Some((key, cert)))
543    }
544
545    /// Like [`KeyMgr::get_key_and_cert`], except this function also generates the subject key
546    /// and its corresponding certificate if they don't already exist.
547    ///
548    /// If the key certificate is missing, it will be generated
549    /// from the subject key and signing key using the provided `make_certificate` callback.
550    ///
551    /// Generates the missing key and/or certificate as follows:
552    ///
553    /// ```text
554    /// | Subject Key exists | Signing Key exists | Cert exists | Action                                 |
555    /// |--------------------|--------------------|-------------|----------------------------------------|
556    /// | Y                  | Y                  | Y           | Validate cert, return key and cert     |
557    /// |                    |                    |             | if valid, error otherwise              |
558    /// |--------------------|--------------------|-------------|----------------------------------------|
559    /// | N                  | Y                  | N           | Generate subject key and               |
560    /// |                    |                    |             | a new cert signed with signing key     |
561    /// |--------------------|--------------------|-------------|----------------------------------------|
562    /// | Y                  | Y                  | N           | Generate cert signed with signing key  |
563    /// |--------------------|--------------------|-------------|----------------------------------------|
564    /// | Y                  | N                  | N           | Error - cannot validate cert           |
565    /// |                    |                    |             | if signing key is not available        |
566    /// |--------------------|--------------------|-------------|----------------------------------------|
567    /// | Y/N                | N                  | N           | Error - cannot generate cert           |
568    /// |                    |                    |             | if signing key is not available        |
569    /// |--------------------|--------------------|-------------|----------------------------------------|
570    /// | N                  | Y/N                | Y           | Error - subject key was removed?       |
571    /// |                    |                    |             | (we found the cert,                    |
572    /// |                    |                    |             | but the subject key is missing)        |
573    /// ```
574    ///
575    //
576    // Note; the table above isn't a markdown table because CommonMark-flavor markdown
577    // doesn't support multiline text in tables. Even if we trim down the text,
578    // the resulting markdown table would be pretty unreadable in raw form
579    // (it would have several excessively long lines, over 120 chars in len).
580    #[cfg(feature = "experimental-api")]
581    pub fn get_or_generate_key_and_cert<K, C>(
582        &self,
583        spec: &dyn KeyCertificateSpecifier,
584        make_certificate: impl FnOnce(&K, &<C as ToEncodableCert<K>>::SigningKey) -> C,
585        selector: KeystoreSelector,
586        rng: &mut dyn KeygenRng,
587    ) -> Result<(K, C)>
588    where
589        K: ToEncodableKey,
590        K::Key: Keygen,
591        C: ToEncodableCert<K>,
592    {
593        let subject_key_spec = spec.subject_key_specifier();
594        let subject_key_arti_path = subject_key_spec
595            .arti_path()
596            .map_err(|_| bad_api_usage!("subject key does not have an ArtiPath?!"))?;
597
598        let cert_specifier =
599            ArtiPath::from_path_and_denotators(subject_key_arti_path, &spec.cert_denotators())
600                .map_err(into_bad_api_usage!("invalid certificate specifier"))?;
601
602        let maybe_cert = self.get_from_store_raw::<C::ParsedCert>(
603            &cert_specifier,
604            &C::ParsedCert::item_type(),
605            self.all_stores(),
606        )?;
607
608        let maybe_subject_key = self.get::<K>(subject_key_spec)?;
609
610        match (&maybe_cert, &maybe_subject_key) {
611            (Some(_), None) => {
612                return Err(KeystoreCorruptionError::MissingSubjectKey.into());
613            }
614            _ => {
615                // generate key and/or cert
616            }
617        }
618        let subject_key = match maybe_subject_key {
619            Some(key) => key,
620            _ => self.generate(subject_key_spec, selector, rng, false)?,
621        };
622
623        let signed_with = self.get_cert_signing_key::<K, C>(spec)?;
624        let cert = match maybe_cert {
625            Some(cert) => C::validate(cert, &subject_key, &signed_with)?,
626            None => {
627                let cert = make_certificate(&subject_key, &signed_with);
628
629                let () = self.insert_cert(cert.clone(), &cert_specifier, selector)?;
630
631                cert
632            }
633        };
634
635        Ok((subject_key, cert))
636    }
637
638    /// Return an iterator over all configured stores.
639    fn all_stores(&self) -> impl Iterator<Item = &BoxedKeystore> {
640        iter::once(&self.primary_store).chain(self.secondary_stores.iter())
641    }
642
643    /// Return the [`Keystore`](crate::Keystore) matching the specified `selector`.
644    ///
645    /// Returns an error if the selected keystore is not the primary keystore or one of the
646    /// configured secondary stores.
647    fn select_keystore(&self, selector: &KeystoreSelector) -> Result<&BoxedKeystore> {
648        match selector {
649            KeystoreSelector::Id(keystore_id) => self.find_keystore(keystore_id),
650            KeystoreSelector::Primary => Ok(&self.primary_store),
651        }
652    }
653
654    /// Return the [`Keystore`](crate::Keystore) with the specified `id`.
655    ///
656    /// Returns an error if the specified ID is not the ID of the primary keystore or
657    /// the ID of one of the configured secondary stores.
658    fn find_keystore(&self, id: &KeystoreId) -> Result<&BoxedKeystore> {
659        self.all_stores()
660            .find(|keystore| keystore.id() == id)
661            .ok_or_else(|| crate::Error::KeystoreNotFound(id.clone()))
662    }
663
664    /// Get the signing key of the certificate described by `spec`.
665    ///
666    /// Returns a [`KeystoreCorruptionError::MissingSigningKey`] error
667    /// if the signing key doesn't exist in any of the keystores.
668    #[cfg(feature = "experimental-api")]
669    fn get_cert_signing_key<K, C>(
670        &self,
671        spec: &dyn KeyCertificateSpecifier,
672    ) -> Result<C::SigningKey>
673    where
674        K: ToEncodableKey,
675        C: ToEncodableCert<K>,
676    {
677        let Some(signing_key_spec) = spec.signing_key_specifier() else {
678            return Err(bad_api_usage!(
679                "signing key specifier is None, but external signing key was not provided?"
680            )
681            .into());
682        };
683
684        let Some(signing_key) = self.get_from_store::<C::SigningKey>(
685            signing_key_spec,
686            &<C::SigningKey as ToEncodableKey>::Key::item_type(),
687            self.all_stores(),
688        )?
689        else {
690            return Err(KeystoreCorruptionError::MissingSigningKey.into());
691        };
692
693        Ok(signing_key)
694    }
695
696    /// Insert `cert` into the [`Keystore`](crate::Keystore) specified by `selector`.
697    ///
698    /// If the key already exists in the specified key store, it will be overwritten.
699    ///
700    // NOTE: if we ever make this public we should rethink/improve its API.
701    // TODO: maybe fold this into insert() somehow?
702    fn insert_cert<K, C>(
703        &self,
704        cert: C,
705        cert_spec: &dyn KeySpecifier,
706        selector: KeystoreSelector,
707    ) -> Result<()>
708    where
709        K: ToEncodableKey,
710        K::Key: Keygen,
711        C: ToEncodableCert<K>,
712    {
713        let cert = cert.to_encodable_cert();
714        let store = self.select_keystore(&selector)?;
715
716        let () = store.insert(&cert, cert_spec)?;
717        Ok(())
718    }
719}
720
721#[cfg(test)]
722mod tests {
723    // @@ begin test lint list maintained by maint/add_warning @@
724    #![allow(clippy::bool_assert_comparison)]
725    #![allow(clippy::clone_on_copy)]
726    #![allow(clippy::dbg_macro)]
727    #![allow(clippy::mixed_attributes_style)]
728    #![allow(clippy::print_stderr)]
729    #![allow(clippy::print_stdout)]
730    #![allow(clippy::single_char_pattern)]
731    #![allow(clippy::unwrap_used)]
732    #![allow(clippy::unchecked_duration_subtraction)]
733    #![allow(clippy::useless_vec)]
734    #![allow(clippy::needless_pass_by_value)]
735    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
736    use super::*;
737    use crate::keystore::arti::err::{ArtiNativeKeystoreError, MalformedPathError};
738    use crate::raw::{RawEntryId, RawKeystoreEntry};
739    use crate::{
740        ArtiPath, ArtiPathUnavailableError, Error, KeyPath, KeystoreEntryResult, KeystoreError,
741        UnrecognizedEntryError,
742    };
743    use std::path::PathBuf;
744    use std::result::Result as StdResult;
745    use std::str::FromStr;
746    use std::sync::{Arc, RwLock};
747    use std::time::{Duration, SystemTime};
748    use tor_basic_utils::test_rng::testing_rng;
749    use tor_cert::CertifiedKey;
750    use tor_cert::Ed25519Cert;
751    use tor_error::{ErrorKind, HasKind};
752    use tor_key_forge::{
753        CertData, EncodableItem, ErasedKey, InvalidCertError, KeyType, KeystoreItem,
754    };
755    use tor_llcrypto::pk::ed25519::{self, Ed25519PublicKey as _};
756    use tor_llcrypto::rng::FakeEntropicRng;
757
758    /// Metadata structure for tracking key operations in tests.
759    #[derive(Clone, Debug, PartialEq)]
760    struct KeyMetadata {
761        /// The identifier for the item (e.g., "coot", "moorhen").
762        item_id: String,
763        /// The keystore from which the item was retrieved.
764        ///
765        /// Set by `Keystore::get`.
766        retrieved_from: Option<KeystoreId>,
767        /// Whether the item was generated via `Keygen::generate`.
768        is_generated: bool,
769    }
770
771    /// Metadata structure for tracking certificate operations in tests.
772    #[derive(Clone, Debug, PartialEq)]
773    struct CertMetadata {
774        /// The identifier for the subject key (e.g., "coot").
775        subject_key_id: String,
776        /// The identifier for the signing key (e.g., "moorhen").
777        signing_key_id: String,
778        /// The keystore from which the certificate was retrieved.
779        ///
780        /// Set by `Keystore::get`.
781        retrieved_from: Option<KeystoreId>,
782        /// Whether the certificate was freshly generated (i.e. returned from the "or generate"
783        /// branch of `get_or_generate()`) or retrieved from a keystore.
784        is_generated: bool,
785    }
786
787    /// Metadata structure for tracking item operations in tests.
788    #[derive(Clone, Debug, PartialEq, derive_more::From)]
789    enum ItemMetadata {
790        /// Metadata about a key.
791        Key(KeyMetadata),
792        /// Metadata about a certificate.
793        Cert(CertMetadata),
794    }
795
796    impl ItemMetadata {
797        /// Get the item ID.
798        ///
799        /// For keys, this returns the key's ID.
800        /// For certificates, this returns a formatted string identifying the subject key.
801        fn item_id(&self) -> &str {
802            match self {
803                ItemMetadata::Key(k) => &k.item_id,
804                ItemMetadata::Cert(c) => &c.subject_key_id,
805            }
806        }
807
808        /// Get retrieved_from.
809        fn retrieved_from(&self) -> Option<&KeystoreId> {
810            match self {
811                ItemMetadata::Key(k) => k.retrieved_from.as_ref(),
812                ItemMetadata::Cert(c) => c.retrieved_from.as_ref(),
813            }
814        }
815
816        /// Get is_generated.
817        fn is_generated(&self) -> bool {
818            match self {
819                ItemMetadata::Key(k) => k.is_generated,
820                ItemMetadata::Cert(c) => c.is_generated,
821            }
822        }
823
824        /// Set the retrieved_from field to the specified keystore ID.
825        fn set_retrieved_from(&mut self, id: KeystoreId) {
826            match self {
827                ItemMetadata::Key(meta) => meta.retrieved_from = Some(id),
828                ItemMetadata::Cert(meta) => meta.retrieved_from = Some(id),
829            }
830        }
831
832        /// Returns a reference to key metadata if this is a Key variant.
833        fn as_key(&self) -> Option<&KeyMetadata> {
834            match self {
835                ItemMetadata::Key(meta) => Some(meta),
836                _ => None,
837            }
838        }
839
840        /// Returns a reference to certificate metadata if this is a Cert variant.
841        fn as_cert(&self) -> Option<&CertMetadata> {
842            match self {
843                ItemMetadata::Cert(meta) => Some(meta),
844                _ => None,
845            }
846        }
847    }
848
849    /// The type of "key" stored in the test key stores.
850    #[derive(Clone, Debug)]
851    struct TestItem {
852        /// The underlying key.
853        item: KeystoreItem,
854        /// Metadata about the key.
855        meta: ItemMetadata,
856    }
857
858    /// A "certificate" used for testing purposes.
859    #[derive(Clone, Debug)]
860    struct AlwaysValidCert(TestItem);
861
862    /// The corresponding fake public key type.
863    #[derive(Clone, Debug)]
864    struct TestPublicKey {
865        /// The underlying key.
866        key: KeystoreItem,
867    }
868
869    impl From<TestItem> for TestPublicKey {
870        fn from(tk: TestItem) -> TestPublicKey {
871            TestPublicKey { key: tk.item }
872        }
873    }
874
875    impl TestItem {
876        /// Create a new test key with the specified metadata.
877        fn new(item_id: &str) -> Self {
878            let mut rng = testing_rng();
879            TestItem {
880                item: ed25519::Keypair::generate(&mut rng)
881                    .as_keystore_item()
882                    .unwrap(),
883                meta: ItemMetadata::Key(KeyMetadata {
884                    item_id: item_id.to_string(),
885                    retrieved_from: None,
886                    is_generated: false,
887                }),
888            }
889        }
890    }
891
892    impl Keygen for TestItem {
893        fn generate(mut rng: &mut dyn KeygenRng) -> tor_key_forge::Result<Self>
894        where
895            Self: Sized,
896        {
897            Ok(TestItem {
898                item: ed25519::Keypair::generate(&mut rng).as_keystore_item()?,
899                meta: ItemMetadata::Key(KeyMetadata {
900                    item_id: "generated_test_key".to_string(),
901                    retrieved_from: None,
902                    is_generated: true,
903                }),
904            })
905        }
906    }
907
908    impl ItemType for TestItem {
909        fn item_type() -> KeystoreItemType
910        where
911            Self: Sized,
912        {
913            // Dummy value
914            KeyType::Ed25519Keypair.into()
915        }
916    }
917
918    impl EncodableItem for TestItem {
919        fn as_keystore_item(&self) -> tor_key_forge::Result<KeystoreItem> {
920            Ok(self.item.clone())
921        }
922    }
923
924    impl ToEncodableKey for TestItem {
925        type Key = Self;
926        type KeyPair = Self;
927
928        fn to_encodable_key(self) -> Self::Key {
929            self
930        }
931
932        fn from_encodable_key(key: Self::Key) -> Self {
933            key
934        }
935    }
936
937    impl ItemType for TestPublicKey {
938        fn item_type() -> KeystoreItemType
939        where
940            Self: Sized,
941        {
942            KeyType::Ed25519PublicKey.into()
943        }
944    }
945
946    impl EncodableItem for TestPublicKey {
947        fn as_keystore_item(&self) -> tor_key_forge::Result<KeystoreItem> {
948            Ok(self.key.clone())
949        }
950    }
951
952    impl ToEncodableKey for TestPublicKey {
953        type Key = Self;
954        type KeyPair = TestItem;
955
956        fn to_encodable_key(self) -> Self::Key {
957            self
958        }
959
960        fn from_encodable_key(key: Self::Key) -> Self {
961            key
962        }
963    }
964
965    impl ToEncodableCert<TestItem> for AlwaysValidCert {
966        type ParsedCert = TestItem;
967        type EncodableCert = TestItem;
968        type SigningKey = TestItem;
969
970        fn validate(
971            cert: Self::ParsedCert,
972            _subject: &TestItem,
973            _signed_with: &Self::SigningKey,
974        ) -> StdResult<Self, InvalidCertError> {
975            // AlwaysValidCert is always valid
976            Ok(Self(cert))
977        }
978
979        /// Convert this cert to a type that implements [`EncodableKey`].
980        fn to_encodable_cert(self) -> Self::EncodableCert {
981            self.0
982        }
983    }
984
985    #[derive(thiserror::Error, Debug, Clone, derive_more::Display)]
986    enum MockKeystoreError {
987        NotFound,
988    }
989
990    impl KeystoreError for MockKeystoreError {}
991
992    impl HasKind for MockKeystoreError {
993        fn kind(&self) -> ErrorKind {
994            // Return a dummy ErrorKind for the purposes of this test
995            tor_error::ErrorKind::Other
996        }
997    }
998
999    fn build_raw_id_path<T: ToString>(key_path: &T, key_type: &KeystoreItemType) -> RawEntryId {
1000        let mut path = key_path.to_string();
1001        path.push('.');
1002        path.push_str(&key_type.arti_extension());
1003        RawEntryId::Path(PathBuf::from(&path))
1004    }
1005
1006    macro_rules! impl_keystore {
1007        ($name:tt, $id:expr $(,$unrec:expr)?) => {
1008            struct $name {
1009                inner: RwLock<
1010                    Vec<StdResult<(ArtiPath, KeystoreItemType, TestItem), UnrecognizedEntryError>>,
1011                >,
1012                id: KeystoreId,
1013            }
1014
1015            impl Default for $name {
1016                fn default() -> Self {
1017                    let id = KeystoreId::from_str($id).unwrap();
1018                    let inner: RwLock<
1019                        Vec<
1020                            StdResult<
1021                                (ArtiPath, KeystoreItemType, TestItem),
1022                                UnrecognizedEntryError,
1023                            >,
1024                        >,
1025                    > = Default::default();
1026                    // Populate the Keystore with the specified number
1027                    // of unrecognized entries.
1028                    $(
1029                        for i in 0..$unrec {
1030                            let invalid_key_path =
1031                                PathBuf::from(&format!("unrecognized_entry{}", i));
1032                            let raw_id = RawEntryId::Path(invalid_key_path.clone());
1033                            let entry = RawKeystoreEntry::new(raw_id, id.clone()).into();
1034                            let entry = UnrecognizedEntryError::new(
1035                                entry,
1036                                Arc::new(ArtiNativeKeystoreError::MalformedPath {
1037                                    path: invalid_key_path,
1038                                    err: MalformedPathError::NoExtension,
1039                                }),
1040                            );
1041                            inner.write().unwrap().push(Err(entry));
1042                        }
1043                    )?
1044                    Self {
1045                        inner,
1046                        id,
1047                    }
1048                }
1049            }
1050
1051            #[allow(dead_code)] // this is only dead code for Keystore1
1052            impl $name {
1053                fn new_boxed() -> BoxedKeystore {
1054                    Box::<Self>::default()
1055                }
1056            }
1057
1058            impl crate::Keystore for $name {
1059                fn contains(
1060                    &self,
1061                    key_spec: &dyn KeySpecifier,
1062                    item_type: &KeystoreItemType,
1063                ) -> Result<bool> {
1064                    let wanted_arti_path = key_spec.arti_path().unwrap();
1065                    Ok(self
1066                        .inner
1067                        .read()
1068                        .unwrap()
1069                        .iter()
1070                        .find(|res| match res {
1071                            Ok((spec, ty, _)) => spec == &wanted_arti_path && ty == item_type,
1072                            Err(_) => false,
1073                        })
1074                        .is_some())
1075                }
1076
1077                fn id(&self) -> &KeystoreId {
1078                    &self.id
1079                }
1080
1081                fn get(
1082                    &self,
1083                    key_spec: &dyn KeySpecifier,
1084                    item_type: &KeystoreItemType,
1085                ) -> Result<Option<ErasedKey>> {
1086                    let key_spec = key_spec.arti_path().unwrap();
1087
1088                    Ok(self.inner.read().unwrap().iter().find_map(|res| {
1089                        match res {
1090                            Ok((arti_path, ty, k)) => {
1091                                if arti_path == &key_spec && ty == item_type {
1092                                    let mut k = k.clone();
1093                                    k.meta.set_retrieved_from(self.id().clone());
1094                                    return Some(Box::new(k) as Box<dyn ItemType>);
1095                                }
1096                            }
1097                            Err(_) => {}
1098                        }
1099                        None
1100                    }))
1101                }
1102
1103                #[cfg(feature = "onion-service-cli-extra")]
1104                fn raw_entry_id(&self, raw_id: &str) -> Result<RawEntryId> {
1105                    Ok(RawEntryId::Path(
1106                        PathBuf::from(raw_id.to_string()),
1107                    ))
1108                }
1109
1110                fn insert(
1111                    &self,
1112                    key: &dyn EncodableItem,
1113                    key_spec: &dyn KeySpecifier,
1114                ) -> Result<()> {
1115                    let key = key.downcast_ref::<TestItem>().unwrap();
1116
1117                    let item = key.as_keystore_item()?;
1118                    let meta = key.meta.clone();
1119
1120                    let item_type = item.item_type()?;
1121                    let key = TestItem { item, meta };
1122
1123                    self.inner
1124                        .write()
1125                        .unwrap()
1126                        // TODO: `insert` is used instead of `push`, because some of the
1127                        // tests (mainly `insert_and_get` and `keygen`) fail otherwise.
1128                        // It could be a good idea to use `push` and adapt the tests,
1129                        // in order to reduce cognitive complexity.
1130                        .insert(0, (Ok((key_spec.arti_path().unwrap(), item_type, key))));
1131
1132                    Ok(())
1133                }
1134
1135                fn remove(
1136                    &self,
1137                    key_spec: &dyn KeySpecifier,
1138                    item_type: &KeystoreItemType,
1139                ) -> Result<Option<()>> {
1140                    let wanted_arti_path = key_spec.arti_path().unwrap();
1141                    let index = self.inner.read().unwrap().iter().position(|res| {
1142                        if let Ok((arti_path, ty, _)) = res {
1143                            arti_path == &wanted_arti_path && ty == item_type
1144                        } else {
1145                            false
1146                        }
1147                    });
1148                    let Some(index) = index else {
1149                        return Ok(None);
1150                    };
1151                    let _ = self.inner.write().unwrap().remove(index);
1152
1153                    Ok(Some(()))
1154                }
1155
1156                #[cfg(feature = "onion-service-cli-extra")]
1157                fn remove_unchecked(&self, entry_id: &RawEntryId) -> Result<()> {
1158                    let index = self.inner.read().unwrap().iter().position(|res| match res {
1159                        Ok((spec, ty, _)) => {
1160                            let id = build_raw_id_path(spec, ty);
1161                            entry_id == &id
1162                        }
1163                        Err(e) => {
1164                            e.entry().raw_id() == entry_id
1165                        }
1166                    });
1167                    let Some(index) = index else {
1168                        return Err(Error::Keystore(Arc::new(MockKeystoreError::NotFound)));
1169                    };
1170                    let _ = self.inner.write().unwrap().remove(index);
1171                    Ok(())
1172                }
1173
1174                fn list(&self) -> Result<Vec<KeystoreEntryResult<KeystoreEntry>>> {
1175                    Ok(self
1176                        .inner
1177                        .read()
1178                        .unwrap()
1179                        .iter()
1180                        .map(|res| match res {
1181                            Ok((arti_path, ty, _)) => {
1182                                let raw_id = RawEntryId::Path(
1183                                    PathBuf::from(
1184                                        &arti_path.to_string(),
1185                                    )
1186                                );
1187
1188                                Ok(KeystoreEntry::new(KeyPath::Arti(arti_path.clone()), ty.clone(), self.id(), raw_id))
1189                            }
1190                            Err(e) => Err(e.clone()),
1191                        })
1192                        .collect())
1193                }
1194            }
1195        };
1196    }
1197
1198    macro_rules! impl_specifier {
1199        ($name:tt, $id:expr) => {
1200            struct $name;
1201
1202            impl KeySpecifier for $name {
1203                fn arti_path(&self) -> StdResult<ArtiPath, ArtiPathUnavailableError> {
1204                    Ok(ArtiPath::new($id.into()).map_err(|e| tor_error::internal!("{e}"))?)
1205                }
1206
1207                fn ctor_path(&self) -> Option<crate::CTorPath> {
1208                    None
1209                }
1210
1211                fn keypair_specifier(&self) -> Option<Box<dyn KeySpecifier>> {
1212                    None
1213                }
1214            }
1215        };
1216    }
1217
1218    impl_keystore!(Keystore1, "keystore1");
1219    impl_keystore!(Keystore2, "keystore2");
1220    impl_keystore!(Keystore3, "keystore3");
1221    impl_keystore!(KeystoreUnrec1, "keystore_unrec1", 1);
1222
1223    impl_specifier!(TestKeySpecifier1, "spec1");
1224    impl_specifier!(TestKeySpecifier2, "spec2");
1225    impl_specifier!(TestKeySpecifier3, "spec3");
1226    impl_specifier!(TestKeySpecifier4, "spec4");
1227
1228    impl_specifier!(TestPublicKeySpecifier1, "pub-spec1");
1229
1230    /// Create a test `KeystoreEntry`.
1231    fn entry_descriptor(specifier: impl KeySpecifier, keystore_id: &KeystoreId) -> KeystoreEntry {
1232        let arti_path = specifier.arti_path().unwrap();
1233        let raw_id = RawEntryId::Path(PathBuf::from(arti_path.as_ref()));
1234        KeystoreEntry {
1235            key_path: arti_path.into(),
1236            key_type: TestItem::item_type(),
1237            keystore_id,
1238            raw_id,
1239        }
1240    }
1241
1242    #[test]
1243    #[allow(clippy::cognitive_complexity)]
1244    fn insert_and_get() {
1245        let mut builder = KeyMgrBuilder::default().primary_store(Box::<Keystore1>::default());
1246
1247        builder
1248            .secondary_stores()
1249            .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]);
1250
1251        let mgr = builder.build().unwrap();
1252
1253        // Insert a key into Keystore2
1254        let old_key = mgr
1255            .insert(
1256                TestItem::new("coot"),
1257                &TestKeySpecifier1,
1258                KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1259                true,
1260            )
1261            .unwrap();
1262
1263        assert!(old_key.is_none());
1264        let key = mgr.get::<TestItem>(&TestKeySpecifier1).unwrap().unwrap();
1265        assert_eq!(key.meta.item_id(), "coot");
1266        assert_eq!(
1267            key.meta.retrieved_from(),
1268            Some(&KeystoreId::from_str("keystore2").unwrap())
1269        );
1270        assert_eq!(key.meta.is_generated(), false);
1271
1272        // Insert a different key using the _same_ key specifier.
1273        let old_key = mgr
1274            .insert(
1275                TestItem::new("gull"),
1276                &TestKeySpecifier1,
1277                KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1278                true,
1279            )
1280            .unwrap()
1281            .unwrap();
1282        assert_eq!(old_key.meta.item_id(), "coot");
1283        assert_eq!(
1284            old_key.meta.retrieved_from(),
1285            Some(&KeystoreId::from_str("keystore2").unwrap())
1286        );
1287        assert_eq!(old_key.meta.is_generated(), false);
1288        // Check that the original value was overwritten:
1289        let key = mgr.get::<TestItem>(&TestKeySpecifier1).unwrap().unwrap();
1290        assert_eq!(key.meta.item_id(), "gull");
1291        assert_eq!(
1292            key.meta.retrieved_from(),
1293            Some(&KeystoreId::from_str("keystore2").unwrap())
1294        );
1295        assert_eq!(key.meta.is_generated(), false);
1296
1297        // Insert a different key using the _same_ key specifier (overwrite = false)
1298        let err = mgr
1299            .insert(
1300                TestItem::new("gull"),
1301                &TestKeySpecifier1,
1302                KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1303                false,
1304            )
1305            .unwrap_err();
1306        assert!(matches!(err, crate::Error::KeyAlreadyExists));
1307
1308        // Insert a new key into Keystore2 (overwrite = false)
1309        let old_key = mgr
1310            .insert(
1311                TestItem::new("penguin"),
1312                &TestKeySpecifier2,
1313                KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1314                false,
1315            )
1316            .unwrap();
1317        assert!(old_key.is_none());
1318
1319        // Insert a key into the primary keystore
1320        let old_key = mgr
1321            .insert(
1322                TestItem::new("moorhen"),
1323                &TestKeySpecifier3,
1324                KeystoreSelector::Primary,
1325                true,
1326            )
1327            .unwrap();
1328        assert!(old_key.is_none());
1329        let key = mgr.get::<TestItem>(&TestKeySpecifier3).unwrap().unwrap();
1330        assert_eq!(key.meta.item_id(), "moorhen");
1331        assert_eq!(
1332            key.meta.retrieved_from(),
1333            Some(&KeystoreId::from_str("keystore1").unwrap())
1334        );
1335        assert_eq!(key.meta.is_generated(), false);
1336
1337        // The key doesn't exist in any of the stores yet.
1338        assert!(mgr.get::<TestItem>(&TestKeySpecifier4).unwrap().is_none());
1339
1340        // Insert the same key into all 3 key stores, in reverse order of keystore priority
1341        // (otherwise KeyMgr::get will return the key from the primary store for each iteration and
1342        // we won't be able to see the key was actually inserted in each store).
1343        for store in ["keystore3", "keystore2", "keystore1"] {
1344            let old_key = mgr
1345                .insert(
1346                    TestItem::new("cormorant"),
1347                    &TestKeySpecifier4,
1348                    KeystoreSelector::Id(&KeystoreId::from_str(store).unwrap()),
1349                    true,
1350                )
1351                .unwrap();
1352            assert!(old_key.is_none());
1353
1354            // Ensure the key now exists in `store`.
1355            let key = mgr.get::<TestItem>(&TestKeySpecifier4).unwrap().unwrap();
1356            assert_eq!(key.meta.item_id(), "cormorant");
1357            assert_eq!(
1358                key.meta.retrieved_from(),
1359                Some(&KeystoreId::from_str(store).unwrap())
1360            );
1361            assert_eq!(key.meta.is_generated(), false);
1362        }
1363
1364        // The key exists in all key stores, but if no keystore_id is specified, we return the
1365        // value from the first key store it is found in (in this case, Keystore1)
1366        let key = mgr.get::<TestItem>(&TestKeySpecifier4).unwrap().unwrap();
1367        assert_eq!(key.meta.item_id(), "cormorant");
1368        assert_eq!(
1369            key.meta.retrieved_from(),
1370            Some(&KeystoreId::from_str("keystore1").unwrap())
1371        );
1372        assert_eq!(key.meta.is_generated(), false);
1373    }
1374
1375    #[test]
1376    fn remove() {
1377        let mut builder = KeyMgrBuilder::default().primary_store(Box::<Keystore1>::default());
1378
1379        builder
1380            .secondary_stores()
1381            .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]);
1382
1383        let mgr = builder.build().unwrap();
1384
1385        assert!(!mgr.secondary_stores[0]
1386            .contains(&TestKeySpecifier1, &TestItem::item_type())
1387            .unwrap());
1388
1389        // Insert a key into Keystore2
1390        mgr.insert(
1391            TestItem::new("coot"),
1392            &TestKeySpecifier1,
1393            KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1394            true,
1395        )
1396        .unwrap();
1397        let key = mgr.get::<TestItem>(&TestKeySpecifier1).unwrap().unwrap();
1398        assert_eq!(key.meta.item_id(), "coot");
1399        assert_eq!(
1400            key.meta.retrieved_from(),
1401            Some(&KeystoreId::from_str("keystore2").unwrap())
1402        );
1403        assert_eq!(key.meta.is_generated(), false);
1404
1405        // Try to remove the key from a non-existent key store
1406        assert!(mgr
1407            .remove::<TestItem>(
1408                &TestKeySpecifier1,
1409                KeystoreSelector::Id(&KeystoreId::from_str("not_an_id_we_know_of").unwrap())
1410            )
1411            .is_err());
1412        // The key still exists in Keystore2
1413        assert!(mgr.secondary_stores[0]
1414            .contains(&TestKeySpecifier1, &TestItem::item_type())
1415            .unwrap());
1416
1417        // Try to remove the key from the primary key store
1418        assert!(mgr
1419            .remove::<TestItem>(&TestKeySpecifier1, KeystoreSelector::Primary)
1420            .unwrap()
1421            .is_none());
1422
1423        // The key still exists in Keystore2
1424        assert!(mgr.secondary_stores[0]
1425            .contains(&TestKeySpecifier1, &TestItem::item_type())
1426            .unwrap());
1427
1428        // Removing from Keystore2 should succeed.
1429        let removed_key = mgr
1430            .remove::<TestItem>(
1431                &TestKeySpecifier1,
1432                KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1433            )
1434            .unwrap()
1435            .unwrap();
1436        assert_eq!(removed_key.meta.item_id(), "coot");
1437        assert_eq!(
1438            removed_key.meta.retrieved_from(),
1439            Some(&KeystoreId::from_str("keystore2").unwrap())
1440        );
1441        assert_eq!(removed_key.meta.is_generated(), false);
1442
1443        // The key doesn't exist in Keystore2 anymore
1444        assert!(!mgr.secondary_stores[0]
1445            .contains(&TestKeySpecifier1, &TestItem::item_type())
1446            .unwrap());
1447    }
1448
1449    #[test]
1450    fn keygen() {
1451        let mut rng = FakeEntropicRng(testing_rng());
1452        let mgr = KeyMgrBuilder::default()
1453            .primary_store(Box::<Keystore1>::default())
1454            .build()
1455            .unwrap();
1456
1457        mgr.insert(
1458            TestItem::new("coot"),
1459            &TestKeySpecifier1,
1460            KeystoreSelector::Primary,
1461            true,
1462        )
1463        .unwrap();
1464
1465        // There is no corresponding public key entry.
1466        assert!(mgr
1467            .get::<TestPublicKey>(&TestPublicKeySpecifier1)
1468            .unwrap()
1469            .is_none());
1470
1471        // Try to generate a new key (overwrite = false)
1472        let err = mgr
1473            .generate::<TestItem>(
1474                &TestKeySpecifier1,
1475                KeystoreSelector::Primary,
1476                &mut rng,
1477                false,
1478            )
1479            .unwrap_err();
1480
1481        assert!(matches!(err, crate::Error::KeyAlreadyExists));
1482
1483        // The previous entry was not overwritten because overwrite = false
1484        let key = mgr.get::<TestItem>(&TestKeySpecifier1).unwrap().unwrap();
1485        assert_eq!(key.meta.item_id(), "coot");
1486        assert_eq!(
1487            key.meta.retrieved_from(),
1488            Some(&KeystoreId::from_str("keystore1").unwrap())
1489        );
1490        assert_eq!(key.meta.is_generated(), false);
1491
1492        // We don't store public keys in the keystore
1493        assert!(mgr
1494            .get::<TestPublicKey>(&TestPublicKeySpecifier1)
1495            .unwrap()
1496            .is_none());
1497
1498        // Try to generate a new key (overwrite = true)
1499        let generated_key = mgr
1500            .generate::<TestItem>(
1501                &TestKeySpecifier1,
1502                KeystoreSelector::Primary,
1503                &mut rng,
1504                true,
1505            )
1506            .unwrap();
1507
1508        assert_eq!(generated_key.meta.item_id(), "generated_test_key");
1509        // Not set in a freshly generated key, because KeyMgr::generate()
1510        // returns it straight away, without going through Keystore::get()
1511        assert_eq!(generated_key.meta.retrieved_from(), None);
1512        assert_eq!(generated_key.meta.is_generated(), true);
1513
1514        // Retrieve the inserted key
1515        let retrieved_key = mgr.get::<TestItem>(&TestKeySpecifier1).unwrap().unwrap();
1516        assert_eq!(retrieved_key.meta.item_id(), "generated_test_key");
1517        assert_eq!(
1518            retrieved_key.meta.retrieved_from(),
1519            Some(&KeystoreId::from_str("keystore1").unwrap())
1520        );
1521        assert_eq!(retrieved_key.meta.is_generated(), true);
1522
1523        // We don't store public keys in the keystore
1524        assert!(mgr
1525            .get::<TestPublicKey>(&TestPublicKeySpecifier1)
1526            .unwrap()
1527            .is_none());
1528    }
1529
1530    #[test]
1531    fn get_or_generate() {
1532        let mut rng = FakeEntropicRng(testing_rng());
1533        let mut builder = KeyMgrBuilder::default().primary_store(Box::<Keystore1>::default());
1534
1535        builder
1536            .secondary_stores()
1537            .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]);
1538
1539        let mgr = builder.build().unwrap();
1540
1541        let keystore2 = KeystoreId::from_str("keystore2").unwrap();
1542        let entry_desc1 = entry_descriptor(TestKeySpecifier1, &keystore2);
1543        assert!(mgr.get_entry::<TestItem>(&entry_desc1).unwrap().is_none());
1544
1545        mgr.insert(
1546            TestItem::new("coot"),
1547            &TestKeySpecifier1,
1548            KeystoreSelector::Id(&keystore2),
1549            true,
1550        )
1551        .unwrap();
1552
1553        // The key already exists in keystore 2 so it won't be auto-generated.
1554        let key = mgr
1555            .get_or_generate::<TestItem>(&TestKeySpecifier1, KeystoreSelector::Primary, &mut rng)
1556            .unwrap();
1557        assert_eq!(key.meta.item_id(), "coot");
1558        assert_eq!(
1559            key.meta.retrieved_from(),
1560            Some(&KeystoreId::from_str("keystore2").unwrap())
1561        );
1562        assert_eq!(key.meta.is_generated(), false);
1563
1564        assert_eq!(
1565            mgr.get_entry::<TestItem>(&entry_desc1)
1566                .unwrap()
1567                .map(|k| k.meta),
1568            Some(ItemMetadata::Key(KeyMetadata {
1569                item_id: "coot".to_string(),
1570                retrieved_from: Some(keystore2.clone()),
1571                is_generated: false,
1572            }))
1573        );
1574
1575        // This key doesn't exist in any of the keystores, so it will be auto-generated and
1576        // inserted into keystore 3.
1577        let keystore3 = KeystoreId::from_str("keystore3").unwrap();
1578        let generated_key = mgr
1579            .get_or_generate::<TestItem>(
1580                &TestKeySpecifier2,
1581                KeystoreSelector::Id(&keystore3),
1582                &mut rng,
1583            )
1584            .unwrap();
1585        assert_eq!(generated_key.meta.item_id(), "generated_test_key");
1586        // Not set in a freshly generated key, because KeyMgr::get_or_generate()
1587        // returns it straight away, without going through Keystore::get()
1588        assert_eq!(generated_key.meta.retrieved_from(), None);
1589        assert_eq!(generated_key.meta.is_generated(), true);
1590
1591        // Retrieve the inserted key
1592        let retrieved_key = mgr.get::<TestItem>(&TestKeySpecifier2).unwrap().unwrap();
1593        assert_eq!(retrieved_key.meta.item_id(), "generated_test_key");
1594        assert_eq!(
1595            retrieved_key.meta.retrieved_from(),
1596            Some(&KeystoreId::from_str("keystore3").unwrap())
1597        );
1598        assert_eq!(retrieved_key.meta.is_generated(), true);
1599
1600        let entry_desc2 = entry_descriptor(TestKeySpecifier2, &keystore3);
1601        assert_eq!(
1602            mgr.get_entry::<TestItem>(&entry_desc2)
1603                .unwrap()
1604                .map(|k| k.meta),
1605            Some(ItemMetadata::Key(KeyMetadata {
1606                item_id: "generated_test_key".to_string(),
1607                retrieved_from: Some(keystore3.clone()),
1608                is_generated: true,
1609            }))
1610        );
1611
1612        let arti_pat = KeyPathPattern::Arti("*".to_string());
1613        let matching = mgr.list_matching(&arti_pat).unwrap();
1614
1615        assert_eq!(matching.len(), 2);
1616        assert!(matching.contains(&entry_desc1));
1617        assert!(matching.contains(&entry_desc2));
1618
1619        assert_eq!(mgr.remove_entry(&entry_desc2).unwrap(), Some(()));
1620        assert!(mgr.get_entry::<TestItem>(&entry_desc2).unwrap().is_none());
1621        assert!(mgr.remove_entry(&entry_desc2).unwrap().is_none());
1622    }
1623
1624    #[test]
1625    fn list_matching_ignores_unrecognized_keys() {
1626        let builder = KeyMgrBuilder::default().primary_store(Box::new(KeystoreUnrec1::default()));
1627
1628        let mgr = builder.build().unwrap();
1629
1630        let unrec_1 = KeystoreId::from_str("keystore_unrec1").unwrap();
1631        mgr.insert(
1632            TestItem::new("whale shark"),
1633            &TestKeySpecifier1,
1634            KeystoreSelector::Id(&unrec_1),
1635            true,
1636        )
1637        .unwrap();
1638
1639        let arti_pat = KeyPathPattern::Arti("*".to_string());
1640        let valid_key_path = KeyPath::Arti(TestKeySpecifier1.arti_path().unwrap());
1641        let matching = mgr.list_matching(&arti_pat).unwrap();
1642        // assert the unrecognized key has been filtered out
1643        assert_eq!(matching.len(), 1);
1644        assert_eq!(matching.first().unwrap().key_path(), &valid_key_path);
1645    }
1646
1647    #[cfg(feature = "onion-service-cli-extra")]
1648    #[test]
1649    /// Test all `arti keys` subcommands
1650    // TODO: split this in different tests
1651    fn keys_subcommands() {
1652        let mut builder =
1653            KeyMgrBuilder::default().primary_store(Box::new(KeystoreUnrec1::default()));
1654        builder
1655            .secondary_stores()
1656            .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]);
1657
1658        let mgr = builder.build().unwrap();
1659        let ks_unrec1id = KeystoreId::from_str("keystore_unrec1").unwrap();
1660        let keystore2id = KeystoreId::from_str("keystore2").unwrap();
1661        let keystore3id = KeystoreId::from_str("keystore3").unwrap();
1662
1663        // Insert a key into KeystoreUnrec1
1664        let _ = mgr
1665            .insert(
1666                TestItem::new("pangolin"),
1667                &TestKeySpecifier1,
1668                KeystoreSelector::Id(&ks_unrec1id),
1669                true,
1670            )
1671            .unwrap();
1672
1673        // Insert a key into Keystore2
1674        let _ = mgr
1675            .insert(
1676                TestItem::new("coot"),
1677                &TestKeySpecifier2,
1678                KeystoreSelector::Id(&keystore2id),
1679                true,
1680            )
1681            .unwrap();
1682
1683        // Insert a key into Keystore3
1684        let _ = mgr
1685            .insert(
1686                TestItem::new("penguin"),
1687                &TestKeySpecifier3,
1688                KeystoreSelector::Id(&keystore3id),
1689                true,
1690            )
1691            .unwrap();
1692
1693        let assert_key = |path, ty, expected_path: &ArtiPath, expected_type| {
1694            assert_eq!(ty, expected_type);
1695            assert_eq!(path, &KeyPath::Arti(expected_path.clone()));
1696        };
1697        let item_type = TestItem::new("axolotl").item.item_type().unwrap();
1698        let unrecognized_entry_id = RawEntryId::Path(PathBuf::from("unrecognized_entry0"));
1699
1700        // Test `list`
1701        let entries = mgr.list().unwrap();
1702
1703        let expected_items = [
1704            (ks_unrec1id, TestKeySpecifier1.arti_path().unwrap()),
1705            (keystore2id, TestKeySpecifier2.arti_path().unwrap()),
1706            (keystore3id, TestKeySpecifier3.arti_path().unwrap()),
1707        ];
1708
1709        // Secondary keystores contain 1 valid key each
1710        let mut recognized_entries = 0;
1711        let mut unrecognized_entries = 0;
1712        for entry in entries.iter() {
1713            match entry {
1714                Ok(e) => {
1715                    if let Some((_, expected_arti_path)) = expected_items
1716                        .iter()
1717                        .find(|(keystore_id, _)| keystore_id == e.keystore_id())
1718                    {
1719                        assert_key(e.key_path(), e.key_type(), expected_arti_path, &item_type);
1720                        recognized_entries += 1;
1721                        continue;
1722                    }
1723
1724                    panic!("Unexpected key encountered {:?}", e);
1725                }
1726                Err(u) => {
1727                    assert_eq!(u.entry().raw_id(), &unrecognized_entry_id);
1728                    unrecognized_entries += 1;
1729                }
1730            }
1731        }
1732        assert_eq!(recognized_entries, 3);
1733        assert_eq!(unrecognized_entries, 1);
1734
1735        // Test `list_keystores`
1736        let keystores = mgr.list_keystores().iter().len();
1737
1738        assert_eq!(keystores, 3);
1739
1740        // Test `list_by_id`
1741        let primary_keystore_id = KeystoreId::from_str("keystore_unrec1").unwrap();
1742        let entries = mgr.list_by_id(&primary_keystore_id).unwrap();
1743
1744        // Primary keystore contains a valid key and an unrecognized key
1745        let mut recognized_entries = 0;
1746        let mut unrecognized_entries = 0;
1747        // A list of entries, in a form that can be consumed by remove_unchecked
1748        let mut all_entries = vec![];
1749        for entry in entries.iter() {
1750            match entry {
1751                Ok(entry) => {
1752                    assert_key(
1753                        entry.key_path(),
1754                        entry.key_type(),
1755                        &TestKeySpecifier1.arti_path().unwrap(),
1756                        &item_type,
1757                    );
1758                    recognized_entries += 1;
1759                    all_entries.push(RawKeystoreEntry::new(
1760                        build_raw_id_path(entry.key_path(), entry.key_type()),
1761                        primary_keystore_id.clone(),
1762                    ));
1763                }
1764                Err(u) => {
1765                    assert_eq!(u.entry().raw_id(), &unrecognized_entry_id);
1766                    unrecognized_entries += 1;
1767                    all_entries.push(u.entry().into());
1768                }
1769            }
1770        }
1771        assert_eq!(recognized_entries, 1);
1772        assert_eq!(unrecognized_entries, 1);
1773
1774        // Remove a recognized entry and an recognized one
1775        for entry in all_entries {
1776            mgr.remove_unchecked(&entry.raw_id().to_string(), entry.keystore_id())
1777                .unwrap();
1778        }
1779
1780        // Check the keys have been removed
1781        let entries = mgr.list_by_id(&primary_keystore_id).unwrap();
1782        assert_eq!(entries.len(), 0);
1783    }
1784
1785    /// Whether to generate a given item before running the `run_certificate_test`.
1786    #[cfg(feature = "experimental-api")]
1787    #[derive(Clone, Copy, Debug, PartialEq)]
1788    enum GenerateItem {
1789        Yes,
1790        No,
1791    }
1792
1793    #[cfg(feature = "experimental-api")]
1794    macro_rules! run_certificate_test {
1795        (
1796            generate_subject_key = $generate_subject_key:expr,
1797            generate_signing_key = $generate_signing_key:expr,
1798            $($expected_err:tt)?
1799        ) => {{
1800            use GenerateItem::*;
1801
1802            let mut rng = FakeEntropicRng(testing_rng());
1803            let mut builder = KeyMgrBuilder::default().primary_store(Box::<Keystore1>::default());
1804
1805            builder
1806                .secondary_stores()
1807                .extend([Keystore2::new_boxed(), Keystore3::new_boxed()]);
1808
1809            let mgr = builder.build().unwrap();
1810
1811            let spec = crate::test_utils::TestCertSpecifier {
1812                subject_key_spec: TestKeySpecifier1,
1813                signing_key_spec: TestKeySpecifier2,
1814                denotator: vec!["foo".into()],
1815            };
1816
1817            if $generate_subject_key == Yes {
1818                let _ = mgr
1819                    .generate::<TestItem>(
1820                        &TestKeySpecifier1,
1821                        KeystoreSelector::Primary,
1822                        &mut rng,
1823                        false,
1824                    )
1825                    .unwrap();
1826            }
1827
1828            if $generate_signing_key == Yes {
1829                let _ = mgr
1830                    .generate::<TestItem>(
1831                        &TestKeySpecifier2,
1832                        KeystoreSelector::Id(&KeystoreId::from_str("keystore2").unwrap()),
1833                        &mut rng,
1834                        false,
1835                    )
1836                    .unwrap();
1837            }
1838
1839            let make_certificate = move |subject_key: &TestItem, signed_with: &TestItem| {
1840                let subject_id = subject_key.meta.as_key().unwrap().item_id.clone();
1841                let signing_id = signed_with.meta.as_key().unwrap().item_id.clone();
1842
1843                let meta = ItemMetadata::Cert(CertMetadata {
1844                    subject_key_id: subject_id,
1845                    signing_key_id: signing_id,
1846                    retrieved_from: None,
1847                    is_generated: true,
1848                });
1849
1850                // Note: this is not really a cert for `subject_key` signed with the `signed_with`
1851                // key!. The two are `TestItem`s and not keys, so we can't really generate a real
1852                // cert from them. We can, however, pretend we did, for testing purposes.
1853                // Eventually we might want to rewrite these tests to use real items
1854                // (like the `ArtiNativeKeystore` tests)
1855                let mut rng = FakeEntropicRng(testing_rng());
1856                let keypair = ed25519::Keypair::generate(&mut rng);
1857                let encoded_cert = Ed25519Cert::constructor()
1858                    .cert_type(tor_cert::CertType::IDENTITY_V_SIGNING)
1859                    .expiration(SystemTime::now() + Duration::from_secs(180))
1860                    .signing_key(keypair.public_key().into())
1861                    .cert_key(CertifiedKey::Ed25519(keypair.public_key().into()))
1862                    .encode_and_sign(&keypair)
1863                    .unwrap();
1864                let test_cert = CertData::TorEd25519Cert(encoded_cert);
1865                AlwaysValidCert(TestItem {
1866                    item: KeystoreItem::Cert(test_cert),
1867                    meta,
1868                })
1869            };
1870
1871            let res = mgr
1872                .get_or_generate_key_and_cert::<TestItem, AlwaysValidCert>(
1873                    &spec,
1874                    &make_certificate,
1875                    KeystoreSelector::Primary,
1876                    &mut rng,
1877                );
1878
1879            #[allow(unused_assignments)]
1880            #[allow(unused_mut)]
1881            let mut has_error = false;
1882            $(
1883                has_error = true;
1884                let err = res.clone().unwrap_err();
1885                assert!(
1886                    matches!(
1887                        err,
1888                        crate::Error::Corruption(KeystoreCorruptionError::$expected_err)
1889                    ),
1890                    "unexpected error: {err:?}",
1891                );
1892            )?
1893
1894            if !has_error {
1895                let (key, cert) = res.unwrap();
1896
1897                let expected_subj_key_id = if $generate_subject_key == Yes {
1898                    "generated_test_key"
1899                } else {
1900                    "generated_test_key"
1901                };
1902
1903                assert_eq!(key.meta.item_id(), expected_subj_key_id);
1904                assert_eq!(
1905                    cert.0.meta.as_cert().unwrap().subject_key_id,
1906                    expected_subj_key_id
1907                );
1908                assert_eq!(
1909                    cert.0.meta.as_cert().unwrap().signing_key_id,
1910                    "generated_test_key"
1911                );
1912                assert_eq!(cert.0.meta.is_generated(), true);
1913            }
1914        }}
1915    }
1916
1917    #[test]
1918    #[cfg(feature = "experimental-api")]
1919    #[rustfmt::skip] // preserve the layout for readability
1920    #[allow(clippy::cognitive_complexity)] // clippy seems confused here...
1921    fn get_certificate() {
1922        run_certificate_test!(
1923            generate_subject_key = No,
1924            generate_signing_key = No,
1925            MissingSigningKey
1926        );
1927
1928        run_certificate_test!(
1929            generate_subject_key = Yes,
1930            generate_signing_key = No,
1931            MissingSigningKey
1932        );
1933
1934        run_certificate_test!(
1935            generate_subject_key = No,
1936            generate_signing_key = Yes,
1937        );
1938
1939        run_certificate_test!(
1940            generate_subject_key = Yes,
1941            generate_signing_key = Yes,
1942        );
1943    }
1944}