Skip to main content

vta_tee/
lib.rs

1pub mod admin_bootstrap;
2pub mod anchor;
3mod detect;
4pub mod did_autogen;
5pub mod kms_bootstrap;
6pub mod mnemonic_guard;
7pub mod provider;
8mod simulated;
9/// Fetch + apply the allowlisted tenant-config overlay over vsock. Only present
10/// in `BAKE_CONFIG=false` (fleet) builds. See design note §3.8.
11#[cfg(feature = "tenant-overlay")]
12pub mod tenant_overlay;
13pub mod types;
14
15// Platform-specific providers (compiled on all targets but only functional
16// on the correct hardware — detection guards against misuse).
17mod nitro;
18mod sev_snp;
19
20use std::sync::Arc;
21
22use tracing::{error, info, warn};
23
24use vta_config::TeeConfig;
25use vta_config::TeeMode;
26use vti_common::error::{AppError, tee_attestation_error};
27
28use self::detect::detect_tee;
29use self::nitro::NitroProvider;
30use self::provider::TeeProvider;
31use self::sev_snp::SevSnpProvider;
32use self::simulated::SimulatedProvider;
33use self::types::{TeeStatus, TeeType};
34
35/// Cached TEE state shared via AppState.
36#[derive(Clone)]
37pub struct TeeState {
38    pub provider: Arc<dyn TeeProvider>,
39    pub status: TeeStatus,
40}
41
42/// Initialize the TEE subsystem based on config.
43///
44/// Returns `Ok(Some(TeeState))` when TEE is active, `Ok(None)` when disabled,
45/// or `Err` when `mode = required` but no TEE hardware is found.
46pub fn init_tee(config: &TeeConfig) -> Result<Option<TeeState>, AppError> {
47    match config.mode {
48        TeeMode::Simulated => {
49            warn!("TEE attestation running in SIMULATED mode — not suitable for production");
50            let provider = SimulatedProvider;
51            let status = provider.detect()?;
52            Ok(Some(TeeState {
53                provider: Arc::new(provider),
54                status,
55            }))
56        }
57        TeeMode::Required | TeeMode::Optional => {
58            match detect_tee() {
59                Some(TeeType::SevSnp) => {
60                    let provider = SevSnpProvider;
61                    let status = provider.detect()?;
62                    info!(platform_version = ?status.platform_version, "TEE initialized: AMD SEV-SNP");
63                    Ok(Some(TeeState {
64                        provider: Arc::new(provider),
65                        status,
66                    }))
67                }
68                Some(TeeType::Nitro) => {
69                    let provider = NitroProvider;
70                    let status = provider.detect()?;
71                    info!("TEE initialized: AWS Nitro Enclaves");
72                    Ok(Some(TeeState {
73                        provider: Arc::new(provider),
74                        status,
75                    }))
76                }
77                Some(TeeType::Simulated) => {
78                    // detect_tee() never returns Simulated, but handle it gracefully
79                    unreachable!("detect_tee() should not return Simulated")
80                }
81                None => {
82                    if config.mode == TeeMode::Required {
83                        error!(
84                            "TEE mode is 'required' but no TEE hardware detected — refusing to start"
85                        );
86                        Err(tee_attestation_error(
87                            "TEE mode is 'required' but no TEE hardware was detected. \
88                             Set tee.mode = 'optional' or 'disabled' to run without TEE, \
89                             or deploy on TEE-capable hardware (AMD SEV-SNP, AWS Nitro).",
90                        ))
91                    } else {
92                        warn!(
93                            "TEE mode is 'optional' but no TEE hardware detected — attestation will not be available"
94                        );
95                        Ok(None)
96                    }
97                }
98            }
99        }
100    }
101}