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