diff --git a/.gitignore b/.gitignore index d7ad289..0febd4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ apploader/conf/local.yml cvmassistants/quote-generator/target + +.vscode diff --git a/cvmassistants/quote-generator/Cargo.lock b/cvmassistants/quote-generator/Cargo.lock new file mode 100644 index 0000000..46901f7 --- /dev/null +++ b/cvmassistants/quote-generator/Cargo.lock @@ -0,0 +1,432 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "jiff" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quote-generator" +version = "1.0.0" +dependencies = [ + "env_logger", + "log", + "tdx-attest-rs", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tdx-attest-rs" +version = "0.1.2" +source = "git+https://github.com/intel/confidential-computing.tee.dcap?tag=DCAP_1.23#e880e54c8f35d44a4763e08dff32a046c8ef2230" +dependencies = [ + "tdx-attest-sys", +] + +[[package]] +name = "tdx-attest-sys" +version = "0.1.0" +source = "git+https://github.com/intel/confidential-computing.tee.dcap?tag=DCAP_1.23#e880e54c8f35d44a4763e08dff32a046c8ef2230" +dependencies = [ + "bindgen", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/cvmassistants/quote-generator/Cargo.toml b/cvmassistants/quote-generator/Cargo.toml index 64d5d53..d3ab95b 100644 --- a/cvmassistants/quote-generator/Cargo.toml +++ b/cvmassistants/quote-generator/Cargo.toml @@ -8,3 +8,4 @@ edition = "2024" tdx-attest-rs = {git = "https://github.com/intel/confidential-computing.tee.dcap", tag = "DCAP_1.23"} log = "0.4" env_logger = "0.11" +thiserror = "2.0" diff --git a/cvmassistants/quote-generator/src/constants.rs b/cvmassistants/quote-generator/src/constants.rs new file mode 100644 index 0000000..71a5441 --- /dev/null +++ b/cvmassistants/quote-generator/src/constants.rs @@ -0,0 +1,3 @@ +pub const REPORT_DATA_SIZE: usize = 64; +pub const REPORT_SIZE: usize = 1024; +pub const TDX_UUID_SIZE: usize = 16; diff --git a/cvmassistants/quote-generator/src/error.rs b/cvmassistants/quote-generator/src/error.rs new file mode 100644 index 0000000..35945f6 --- /dev/null +++ b/cvmassistants/quote-generator/src/error.rs @@ -0,0 +1,27 @@ +use std::array::TryFromSliceError; +use std::io; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum QuoteGeneratorError { + #[error("Invalid usage: expected exactly 1 argument (report data), received {actual}")] + InvalidUsage { actual: usize }, + + #[error("Report data must be at most {max} bytes, got {actual} bytes")] + ReportDataTooLarge { max: usize, actual: usize }, + + #[error("Failed to convert report data: {0}")] + ReportDataConversion(#[from] TryFromSliceError), + + #[error("Failed to get TDX report")] + TdxReportFailed, + + #[error("Failed to get TDX quote")] + TdxQuoteFailed, + + #[error("TDX quote generation returned no data")] + TdxQuoteEmpty, + + #[error("Failed to write quote file: {0}")] + WriteQuoteFile(#[from] io::Error), +} diff --git a/cvmassistants/quote-generator/src/main.rs b/cvmassistants/quote-generator/src/main.rs index d6feb50..1400f5e 100644 --- a/cvmassistants/quote-generator/src/main.rs +++ b/cvmassistants/quote-generator/src/main.rs @@ -29,135 +29,50 @@ * */ -use log::{debug, error, info}; +use log::{debug, info}; use std::env; use std::fs; -use std::process; -use tdx_attest_rs; +mod error; +use error::QuoteGeneratorError; +mod utils; +use utils::{create_quote, create_report_data, create_tdx_report}; +mod constants; +use constants::REPORT_DATA_SIZE; -const REPORT_DATA_SIZE: usize = 64; -const REPORT_SIZE: usize = 1024; -const TDX_UUID_SIZE: usize = 16; -const QUOTE_FILE_NAME: &str = "quote.dat"; - -/// Creates a TDX report data structure from input bytes. -/// -/// # Arguments -/// -/// * `input_bytes` - A byte slice that **must be exactly `REPORT_DATA_SIZE` bytes long**. -/// In this binary, `main` guarantees this by copying/padding the user input into -/// a fixed-size `REPORT_DATA_SIZE` buffer before calling this function. -/// -/// # Returns -/// -/// A `tdx_report_data_t` structure containing the input bytes. -/// -/// # Panics -/// -/// Panics if `input_bytes` length doesn't match `REPORT_DATA_SIZE` (due to `try_into().unwrap()`). -fn create_report_data(input_bytes: &[u8]) -> tdx_attest_rs::tdx_report_data_t { - let report_data = tdx_attest_rs::tdx_report_data_t { - d: input_bytes.try_into().unwrap(), - }; - debug!("TDX report data: {:?}", report_data.d); - - report_data -} - -/// Generates and displays a TDX report for the given report data. -/// -/// This function creates a TDX report and logs it at debug level. -/// The report is only visible when the logger is configured to show debug messages. -/// -/// # Arguments -/// -/// * `report_data` - The report data to use for generating the TDX report -/// -/// # Exits -/// -/// Exits with status code 1 if the report generation fails -fn display_tdx_report(report_data: &tdx_attest_rs::tdx_report_data_t) { - let mut tdx_report = tdx_attest_rs::tdx_report_t { - d: [0; REPORT_SIZE], - }; - let result = tdx_attest_rs::tdx_att_get_report(Some(report_data), &mut tdx_report); - if result != tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS { - error!("Failed to get the report"); - process::exit(1); - } - debug!("TDX report: {:?}", tdx_report.d); -} - -/// Creates a TDX attestation quote from the given report data. -/// -/// This function generates a cryptographic quote that can be used to verify -/// the integrity and authenticity of the TDX environment. -/// -/// # Arguments -/// -/// * `report_data` - The report data to include in the quote -/// -/// # Returns -/// -/// A `Vec` containing the generated quote data -/// -/// # Exits -/// -/// Exits with status code 1 if quote generation fails -fn create_quote(report_data: &tdx_attest_rs::tdx_report_data_t) -> Vec { - let mut selected_att_key_id = tdx_attest_rs::tdx_uuid_t { - d: [0; TDX_UUID_SIZE], - }; - let (result, quote) = tdx_attest_rs::tdx_att_get_quote( - Some(report_data), - None, - Some(&mut selected_att_key_id), - 0, - ); - if result != tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS { - error!("Failed to get the quote"); - process::exit(1); - } - match quote { - Some(q) => { - debug!("Successfully generated TDX quote with {} bytes", q.len()); - debug!("Quote: {:?}", q); - q - } - None => { - error!("Failed to get the quote"); - process::exit(1); - } - } -} - -fn main() { +fn main() -> Result<(), QuoteGeneratorError> { // Initialize the logger (defaults to INFO level, override with RUST_LOG env var) env_logger::init(); let args: Vec = env::args().collect(); if args.len() != 2 { - error!("Usage: {} <{}-byte-report-data>", args[0], REPORT_DATA_SIZE); - process::exit(1); + return Err(QuoteGeneratorError::InvalidUsage { + actual: args.len() - 1, + }); } let input = &args[1]; let input_bytes = input.as_bytes(); if input_bytes.len() > REPORT_DATA_SIZE { - error!( - "report_data must be at most {} bytes, got {} bytes", - REPORT_DATA_SIZE, - input_bytes.len() - ); - process::exit(1); + return Err(QuoteGeneratorError::ReportDataTooLarge { + max: REPORT_DATA_SIZE, + actual: input_bytes.len(), + }); } let mut report_bytes = [0u8; REPORT_DATA_SIZE]; report_bytes[..input_bytes.len()].copy_from_slice(input_bytes); - let report_data = create_report_data(&report_bytes); - display_tdx_report(&report_data); // Report is only displayed on debug mode - this function is optional - let quote = create_quote(&report_data); - fs::write(QUOTE_FILE_NAME, quote).expect("Unable to write quote file"); - info!("Quote successfully written to {}", QUOTE_FILE_NAME); + let report_data = create_report_data(&report_bytes)?; + debug!("Report data: {:?}", report_data.d); + if log::log_enabled!(log::Level::Debug) { + let tdx_report = create_tdx_report(&report_data)?; + debug!("TDX report: {:?}", tdx_report.d); + } + let quote = create_quote(&report_data)?; + debug!("Quote: {:?}", quote); + let quote_filename = format!("quote-{}.dat", input); + fs::write("e_filename, quote)?; + info!("Quote successfully written to {}", quote_filename); + + Ok(()) } diff --git a/cvmassistants/quote-generator/src/utils.rs b/cvmassistants/quote-generator/src/utils.rs new file mode 100644 index 0000000..9093778 --- /dev/null +++ b/cvmassistants/quote-generator/src/utils.rs @@ -0,0 +1,99 @@ +use crate::constants::{REPORT_SIZE, TDX_UUID_SIZE}; +use crate::error::QuoteGeneratorError; +use log::error; + +/// Creates a TDX report data structure from input bytes. +/// +/// # Arguments +/// +/// * `input_bytes` - A byte slice that **must be exactly `REPORT_DATA_SIZE` bytes long**. +/// In this binary, `main` guarantees this by copying/padding the user input into +/// a fixed-size `REPORT_DATA_SIZE` buffer before calling this function. +/// +/// # Returns +/// +/// A `Result` containing the `tdx_report_data_t` structure, or a `QuoteGeneratorError` +/// if the input bytes cannot be converted. +/// +/// # Errors +/// +/// Returns `QuoteGeneratorError::ReportDataConversion` if input bytes length doesn't match `REPORT_DATA_SIZE`. +pub fn create_report_data( + input_bytes: &[u8], +) -> Result { + let report_data = tdx_attest_rs::tdx_report_data_t { + d: input_bytes.try_into()?, + }; + Ok(report_data) +} + +/// Creates a TDX report from the given report data. +/// +/// # Arguments +/// +/// * `report_data` - The report data to use for generating the TDX report +/// +/// # Returns +/// +/// A `Result` containing the `tdx_report_t` structure on success. +/// +/// # Errors +/// +/// Returns `QuoteGeneratorError::TdxReportFailed` if the report generation fails. +pub fn create_tdx_report( + report_data: &tdx_attest_rs::tdx_report_data_t, +) -> Result { + let mut tdx_report = tdx_attest_rs::tdx_report_t { + d: [0; REPORT_SIZE], + }; + let result = tdx_attest_rs::tdx_att_get_report(Some(report_data), &mut tdx_report); + match result { + tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => Ok(tdx_report), + _ => { + error!("Failed to get TDX report: {:?}", result); + Err(QuoteGeneratorError::TdxReportFailed) // _tdx_attest_error_t does not implement std::error::Error + } + } +} + +/// Creates a TDX attestation quote from the given report data. +/// +/// This function generates a cryptographic quote that can be used to verify +/// the integrity and authenticity of the TDX environment. +/// +/// # Arguments +/// +/// * `report_data` - The report data to include in the quote +/// +/// # Returns +/// +/// A `Result` containing the generated quote data as `Vec` on success. +/// +/// # Errors +/// +/// * `QuoteGeneratorError::TdxQuoteFailed` - if the quote generation API call fails. +/// * `QuoteGeneratorError::TdxQuoteEmpty` - if the API succeeds but returns no quote data. +pub fn create_quote( + report_data: &tdx_attest_rs::tdx_report_data_t, +) -> Result, QuoteGeneratorError> { + let mut selected_att_key_id = tdx_attest_rs::tdx_uuid_t { + d: [0; TDX_UUID_SIZE], + }; + let (result, quote) = tdx_attest_rs::tdx_att_get_quote( + Some(report_data), + None, + Some(&mut selected_att_key_id), + 0, + ); + + match result { + tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => match quote { + Some(q) => Ok(q), + None => Err(QuoteGeneratorError::TdxQuoteEmpty), + }, + _ => { + error!("Failed to get TDX quote: {:?}", result); + Err(QuoteGeneratorError::TdxQuoteFailed) // _tdx_attest_error_t does not implement std::error::Error + } + } +}