Skip to main content

key_vault/fetcher/
tpm.rs

1//! [`TpmFetch`] — TPM 2.0 [`KeyFetch`] backend (**detection-only in 1.0**).
2//!
3//! 1.0 ships TPM **detection** via
4//! [`detect_tee_capabilities`](crate::tee::detect_tee_capabilities) — the
5//! CPUID-based probe will tell you whether a TPM-equipped TEE is present
6//! on the host. Full TPM **acquisition** (talking to the TPM, unsealing
7//! keys, attestation) is on the 1.x roadmap and requires deep integration
8//! with `tss-esapi` or equivalent.
9//!
10//! Calling [`TpmFetch::fetch`] in 1.0 always returns
11//! [`Error::Acquisition`](crate::Error::Acquisition) with a documented
12//! message so consumers can fall through to another fetcher in a
13//! composite arrangement without a panic.
14//!
15//! # When this exists despite returning errors
16//!
17//! Code that wants to declare its intended fetcher hierarchy at
18//! configuration time — e.g. "prefer TPM, then keychain, then file" —
19//! can wire `TpmFetch` into its chain and inherit the 1.x upgrade
20//! automatically when full integration ships.
21
22use alloc::borrow::Cow;
23use alloc::string::ToString;
24
25use super::{FetchContext, KeyFetch, RawKey};
26use crate::Result;
27use crate::error::Error;
28
29/// Detection-only TPM 2.0 fetcher.
30///
31/// Always returns
32/// [`Error::Acquisition`](crate::Error::Acquisition) in 1.0. Use the TEE
33/// detection probe ([`detect_tee_capabilities`](crate::tee::detect_tee_capabilities))
34/// to check whether a TPM is present at all.
35///
36/// # Examples
37///
38/// ```
39/// use key_vault::{FetchContext, KeyFetch, TpmFetch};
40///
41/// let fetcher = TpmFetch;
42/// let err = fetcher.fetch(&FetchContext::new("k")).unwrap_err();
43/// // 1.0 ships detection only — full TPM integration is in the 1.x roadmap.
44/// assert!(format!("{err}").contains("TPM"));
45/// ```
46#[derive(Debug, Default, Clone, Copy)]
47pub struct TpmFetch;
48
49impl KeyFetch for TpmFetch {
50    fn fetch(&self, _ctx: &FetchContext) -> Result<RawKey> {
51        Err(Error::Acquisition {
52            source: Cow::Borrowed("tpm"),
53            reason:
54                "TPM 2.0 acquisition is detection-only in 1.0; full integration arrives in the \
55                 1.x release line. Use detect_tee_capabilities() to probe for TPM presence."
56                    .to_string(),
57        })
58    }
59
60    fn describe(&self) -> Cow<'_, str> {
61        Cow::Borrowed("tpm")
62    }
63}
64
65#[cfg(test)]
66#[allow(clippy::unwrap_used, clippy::expect_used)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn fetch_returns_detection_only_error() {
72        let err = TpmFetch.fetch(&FetchContext::new("k")).unwrap_err();
73        match err {
74            Error::Acquisition { source, reason } => {
75                assert_eq!(source, "tpm");
76                assert!(reason.contains("detection-only"));
77            }
78            other => panic!("expected Acquisition, got {other:?}"),
79        }
80    }
81
82    #[test]
83    fn describe_returns_tpm() {
84        assert_eq!(TpmFetch.describe(), "tpm");
85    }
86}