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}