az_tdx_vtpm/lib.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This library enables guest attestation flows for [TDX CVMs on Azure](https://learn.microsoft.com/en-us/azure/confidential-computing/tdx-confidential-vm-overview).
5//!
6//! A TD report can be retrieved in parsed form using `report::get_report()` function, or as
7//! raw bytes including the hcl envelope using `vtpm::get_report()`. The library provides a
8//! function to retrieve the TD quote from the Azure Instance Metadata Service (IMDS) using
9//! `imds::get_td_quote()`, produce returning a quote signed by a TDX Quoting Enclave.
10//!
11//! Variable Data is part of the HCL envelope and holds the public part of the vTPM Attestation
12//! Key (AK). A hash of the Variable Data block is included in the TD report as `reportdata`.
13//! TPM quotes retrieved with `vtpm::get_quote()` should be signed by this AK. A verification
14//! function would need to check this to ensure the TD report is linked to this unique TDX CVM.
15//!
16//! #
17//! ```no_run
18//! use az_tdx_vtpm::{hcl, imds, report, tdx, vtpm};
19//! use openssl::pkey::{PKey, Public};
20//! use std::error::Error;
21//!
22//! fn main() -> Result<(), Box<dyn Error>> {
23//! let td_report = report::get_report()?;
24//! let td_quote_bytes = imds::get_td_quote(&td_report)?;
25//! std::fs::write("td_quote.bin", td_quote_bytes)?;
26//!
27//! let bytes = vtpm::get_report()?;
28//! let hcl_report = hcl::HclReport::new(bytes)?;
29//! let var_data_hash = hcl_report.var_data_sha256();
30//! let ak_pub = hcl_report.ak_pub()?;
31//!
32//! let td_report: tdx::TdReport = hcl_report.try_into()?;
33//! assert!(var_data_hash == td_report.report_mac.reportdata[..32]);
34//! let nonce = "a nonce".as_bytes();
35//!
36//! let tpm_quote = vtpm::get_quote(nonce)?;
37//! let der = ak_pub.key.try_to_der()?;
38//! let pub_key = PKey::public_key_from_der(&der)?;
39//! tpm_quote.verify(&pub_key, nonce)?;
40//!
41//! Ok(())
42//! }
43//! ```
44
45pub mod imds;
46pub mod report;
47pub use az_cvm_vtpm::{hcl, tdx, vtpm};
48
49/// Determines if the current VM is a TDX CVM.
50/// Returns `Ok(true)` if the VM is a TDX CVM, `Ok(false)` if it is not,
51/// and `Err` if an error occurs.
52pub fn is_tdx_cvm() -> Result<bool, vtpm::ReportError> {
53 let bytes = vtpm::get_report()?;
54 let Ok(hcl_report) = hcl::HclReport::new(bytes) else {
55 return Ok(false);
56 };
57 let is_tdx = hcl_report.report_type() == hcl::ReportType::Tdx;
58 Ok(is_tdx)
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use hcl::HclReport;
65 use tdx::TdReport;
66
67 #[test]
68 fn test_report_data_hash() {
69 let bytes: &[u8] = include_bytes!("../../test/hcl-report-tdx.bin");
70 let hcl_report = HclReport::new(bytes.to_vec()).unwrap();
71 let var_data_hash = hcl_report.var_data_sha256();
72 let td_report: TdReport = hcl_report.try_into().unwrap();
73 assert!(var_data_hash == td_report.report_mac.reportdata[..32]);
74 }
75}