1use crate::Tpm;
5use crate::TpmError;
6use crate::ak_cert::TpmAkCertType;
7use async_trait::async_trait;
8use chipset_device_resources::ResolveChipsetDeviceHandleParams;
9use chipset_device_resources::ResolvedChipsetDevice;
10use thiserror::Error;
11use tpm_resources::TpmAkCertTypeResource;
12use tpm_resources::TpmDeviceHandle;
13use vm_resource::AsyncResolveResource;
14use vm_resource::ResolveError;
15use vm_resource::ResourceResolver;
16use vm_resource::declare_static_async_resolver;
17use vm_resource::kind::ChipsetDeviceHandleKind;
18
19pub struct TpmDeviceResolver;
20
21declare_static_async_resolver! {
22 TpmDeviceResolver,
23 (ChipsetDeviceHandleKind, TpmDeviceHandle),
24}
25
26#[derive(Debug, Error)]
27pub enum ResolveTpmError {
28 #[error("error resolving ppi store")]
29 ResolvePpiStore(#[source] ResolveError),
30 #[error("error resolving nvram store")]
31 ResolveNvramStore(#[source] ResolveError),
32 #[error("error resolving get attestation report")]
33 ResolveGetAttestationReport(#[source] ResolveError),
34 #[error("error resolving request ak cert")]
35 ResolveRequestAkCert(#[source] ResolveError),
36 #[error("error resolving request TPM logger")]
37 ResolveTpmLogger(#[source] ResolveError),
38 #[error("error creating tpm")]
39 Tpm(#[source] TpmError),
40 #[error(
41 "invalid AK cert type: `get_attestation_report` is `Some`, `request_ak_cert` is `None`"
42 )]
43 InvalidAkCertType,
44}
45
46#[async_trait]
47impl AsyncResolveResource<ChipsetDeviceHandleKind, TpmDeviceHandle> for TpmDeviceResolver {
48 type Error = ResolveTpmError;
49 type Output = ResolvedChipsetDevice;
50
51 async fn resolve(
52 &self,
53 resolver: &ResourceResolver,
54 resource: TpmDeviceHandle,
55 input: ResolveChipsetDeviceHandleParams<'_>,
56 ) -> Result<Self::Output, Self::Error> {
57 let ppi_store = resolver
58 .resolve(resource.ppi_store, ())
59 .await
60 .map_err(ResolveTpmError::ResolvePpiStore)?;
61
62 let nvram_store = resolver
63 .resolve(resource.nvram_store, ())
64 .await
65 .map_err(ResolveTpmError::ResolveNvramStore)?;
66
67 let ak_cert_type = match resource.ak_cert_type {
68 TpmAkCertTypeResource::HwAttested(request_ak_cert) => TpmAkCertType::HwAttested(
69 resolver
70 .resolve(request_ak_cert, &())
71 .await
72 .map_err(ResolveTpmError::ResolveRequestAkCert)?
73 .0,
74 ),
75 TpmAkCertTypeResource::Trusted(request_ak_cert) => TpmAkCertType::Trusted(
76 resolver
77 .resolve(request_ak_cert, &())
78 .await
79 .map_err(ResolveTpmError::ResolveRequestAkCert)?
80 .0,
81 ),
82 TpmAkCertTypeResource::None => TpmAkCertType::None,
83 };
84
85 let monotonic_timer = Box::new({
89 let vmtime = input.vmtime.access("tpm");
90 move || {
91 const NUM_100NS_IN_SEC: u64 = 10 * 1000 * 1000;
92 let n = vmtime.now().as_100ns();
93 std::time::Duration::new(n / NUM_100NS_IN_SEC, (n % NUM_100NS_IN_SEC) as u32 * 100)
94 }
95 });
96
97 let logger = if let Some(r) = resource.logger {
98 Some(
99 resolver
100 .resolve(r, &())
101 .await
102 .map_err(ResolveTpmError::ResolveTpmLogger)?
103 .0,
104 )
105 } else {
106 None
107 };
108
109 let tpm = Tpm::new(
110 resource.register_layout,
111 input.encrypted_guest_memory.clone(),
112 ppi_store.0,
113 nvram_store.0,
114 monotonic_timer,
115 resource.refresh_tpm_seeds,
116 input.is_restoring,
117 ak_cert_type,
118 resource.guest_secret_key,
119 logger,
120 )
121 .await
122 .map_err(ResolveTpmError::Tpm)?;
123
124 Ok(tpm.into())
125 }
126}