From f1661f1f7868eca30b08bb50692b17f8b3183e97 Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 22 Mar 2024 15:01:04 +0800 Subject: [PATCH 1/2] AS/Verifier: add support for TDX Quote v5 Close #352 Signed-off-by: Xynnn007 --- .../verifier/src/az_tdx_vtpm/mod.rs | 2 +- .../verifier/src/tdx/claims.rs | 129 +++++--- attestation-service/verifier/src/tdx/mod.rs | 12 +- attestation-service/verifier/src/tdx/quote.rs | 297 ++++++++++++++++-- .../verifier/test_data/tdx_quote_5.dat | Bin 0 -> 5006 bytes 5 files changed, 372 insertions(+), 68 deletions(-) create mode 100644 attestation-service/verifier/test_data/tdx_quote_5.dat diff --git a/attestation-service/verifier/src/az_tdx_vtpm/mod.rs b/attestation-service/verifier/src/az_tdx_vtpm/mod.rs index 3e41add46..2e85da789 100644 --- a/attestation-service/verifier/src/az_tdx_vtpm/mod.rs +++ b/attestation-service/verifier/src/az_tdx_vtpm/mod.rs @@ -72,7 +72,7 @@ impl Verifier for AzTdxVtpm { fn verify_hcl_var_data(hcl_report: &HclReport, td_quote: &TdQuote) -> Result<()> { let var_data_hash = hcl_report.var_data_sha256(); - if var_data_hash != td_quote.report_body.report_data[..32] { + if var_data_hash != td_quote.report_data()[..32] { bail!("TDX Quote report data mismatch"); } debug!("Report data verification completed successfully."); diff --git a/attestation-service/verifier/src/tdx/claims.rs b/attestation-service/verifier/src/tdx/claims.rs index ed9e1a3be..a911b56d5 100644 --- a/attestation-service/verifier/src/tdx/claims.rs +++ b/attestation-service/verifier/src/tdx/claims.rs @@ -50,7 +50,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use log::{debug, warn}; use serde_json::{Map, Value}; -use crate::TeeEvidenceParsedClaim; +use crate::{tdx::quote::QuoteV5Body, TeeEvidenceParsedClaim}; use super::{ eventlog::{CcEventLog, MeasuredEntity}, @@ -76,41 +76,94 @@ pub fn generate_parsed_claim( let mut quote_map = Map::new(); let mut quote_body = Map::new(); let mut quote_header = Map::new(); - // Claims from TD Quote Header. - parse_claim!(quote_header, "version", quote.header.version); - parse_claim!(quote_header, "att_key_type", quote.header.att_key_type); - parse_claim!(quote_header, "tee_type", quote.header.tee_type); - parse_claim!(quote_header, "reserved", quote.header.reserved); - parse_claim!(quote_header, "vendor_id", quote.header.vendor_id); - parse_claim!(quote_header, "user_data", quote.header.user_data); - // Claims from TD Quote Body. We ignore RTMRs because when verifying the integrity of - // the eventlog (CCEL), they have already been consumed. - parse_claim!(quote_body, "tcb_svn", quote.report_body.tcb_svn); - parse_claim!(quote_body, "mr_seam", quote.report_body.mr_seam); - parse_claim!(quote_body, "mrsigner_seam", quote.report_body.mrsigner_seam); - parse_claim!( - quote_body, - "seam_attributes", - quote.report_body.seam_attributes - ); - parse_claim!(quote_body, "td_attributes", quote.report_body.td_attributes); - parse_claim!(quote_body, "xfam", quote.report_body.xfam); - parse_claim!(quote_body, "mr_td", quote.report_body.mr_td); - parse_claim!(quote_body, "mr_config_id", quote.report_body.mr_config_id); - parse_claim!(quote_body, "mr_owner", quote.report_body.mr_owner); - parse_claim!( - quote_body, - "mr_owner_config", - quote.report_body.mr_owner_config - ); - parse_claim!(quote_body, "rtmr_0", quote.report_body.rtmr_0); - parse_claim!(quote_body, "rtmr_1", quote.report_body.rtmr_1); - parse_claim!(quote_body, "rtmr_2", quote.report_body.rtmr_2); - parse_claim!(quote_body, "rtmr_3", quote.report_body.rtmr_3); - parse_claim!(quote_body, "report_data", quote.report_body.report_data); - - parse_claim!(quote_map, "header", quote_header); - parse_claim!(quote_map, "body", quote_body); + + match "e { + Quote::V4 { header, body } => { + parse_claim!(quote_header, "version", b"\x04\x00"); + parse_claim!(quote_header, "att_key_type", header.att_key_type); + parse_claim!(quote_header, "tee_type", header.tee_type); + parse_claim!(quote_header, "reserved", header.reserved); + parse_claim!(quote_header, "vendor_id", header.vendor_id); + parse_claim!(quote_header, "user_data", header.user_data); + parse_claim!(quote_body, "tcb_svn", body.tcb_svn); + parse_claim!(quote_body, "mr_seam", body.mr_seam); + parse_claim!(quote_body, "mrsigner_seam", body.mrsigner_seam); + parse_claim!(quote_body, "seam_attributes", body.seam_attributes); + parse_claim!(quote_body, "td_attributes", body.td_attributes); + parse_claim!(quote_body, "xfam", body.xfam); + parse_claim!(quote_body, "mr_td", body.mr_td); + parse_claim!(quote_body, "mr_config_id", body.mr_config_id); + parse_claim!(quote_body, "mr_owner", body.mr_owner); + parse_claim!(quote_body, "mr_owner_config", body.mr_owner_config); + parse_claim!(quote_body, "rtmr_0", body.rtmr_0); + parse_claim!(quote_body, "rtmr_1", body.rtmr_1); + parse_claim!(quote_body, "rtmr_2", body.rtmr_2); + parse_claim!(quote_body, "rtmr_3", body.rtmr_3); + parse_claim!(quote_body, "report_data", body.report_data); + + parse_claim!(quote_map, "header", quote_header); + parse_claim!(quote_map, "body", quote_body); + } + Quote::V5 { + header, + r#type, + size, + body, + } => { + parse_claim!(quote_header, "version", b"\x05\x00"); + parse_claim!(quote_header, "att_key_type", header.att_key_type); + parse_claim!(quote_header, "tee_type", header.tee_type); + parse_claim!(quote_header, "reserved", header.reserved); + parse_claim!(quote_header, "vendor_id", header.vendor_id); + parse_claim!(quote_header, "user_data", header.user_data); + parse_claim!(quote_map, "type", r#type.as_bytes()); + parse_claim!(quote_map, "size", &size[..]); + match body { + QuoteV5Body::Tdx10(body) => { + parse_claim!(quote_body, "tcb_svn", body.tcb_svn); + parse_claim!(quote_body, "mr_seam", body.mr_seam); + parse_claim!(quote_body, "mrsigner_seam", body.mrsigner_seam); + parse_claim!(quote_body, "seam_attributes", body.seam_attributes); + parse_claim!(quote_body, "td_attributes", body.td_attributes); + parse_claim!(quote_body, "xfam", body.xfam); + parse_claim!(quote_body, "mr_td", body.mr_td); + parse_claim!(quote_body, "mr_config_id", body.mr_config_id); + parse_claim!(quote_body, "mr_owner", body.mr_owner); + parse_claim!(quote_body, "mr_owner_config", body.mr_owner_config); + parse_claim!(quote_body, "rtmr_0", body.rtmr_0); + parse_claim!(quote_body, "rtmr_1", body.rtmr_1); + parse_claim!(quote_body, "rtmr_2", body.rtmr_2); + parse_claim!(quote_body, "rtmr_3", body.rtmr_3); + parse_claim!(quote_body, "report_data", body.report_data); + + parse_claim!(quote_map, "header", quote_header); + parse_claim!(quote_map, "body", quote_body); + } + QuoteV5Body::Tdx15(body) => { + parse_claim!(quote_body, "tcb_svn", body.tcb_svn); + parse_claim!(quote_body, "mr_seam", body.mr_seam); + parse_claim!(quote_body, "mrsigner_seam", body.mrsigner_seam); + parse_claim!(quote_body, "seam_attributes", body.seam_attributes); + parse_claim!(quote_body, "td_attributes", body.td_attributes); + parse_claim!(quote_body, "xfam", body.xfam); + parse_claim!(quote_body, "mr_td", body.mr_td); + parse_claim!(quote_body, "mr_config_id", body.mr_config_id); + parse_claim!(quote_body, "mr_owner", body.mr_owner); + parse_claim!(quote_body, "mr_owner_config", body.mr_owner_config); + parse_claim!(quote_body, "rtmr_0", body.rtmr_0); + parse_claim!(quote_body, "rtmr_1", body.rtmr_1); + parse_claim!(quote_body, "rtmr_2", body.rtmr_2); + parse_claim!(quote_body, "rtmr_3", body.rtmr_3); + parse_claim!(quote_body, "report_data", body.report_data); + + parse_claim!(quote_body, "tee_tcb_svn2", body.tee_tcb_svn2); + parse_claim!(quote_body, "mr_servicetd", body.mr_servicetd); + parse_claim!(quote_map, "header", quote_header); + parse_claim!(quote_map, "body", quote_body); + } + } + } + } // Claims from CC EventLog. let mut ccel_map = Map::new(); @@ -124,8 +177,8 @@ pub fn generate_parsed_claim( parse_claim!(claims, "quote", quote_map); parse_claim!(claims, "ccel", ccel_map); - parse_claim!(claims, "report_data", quote.report_body.report_data); - parse_claim!(claims, "init_data", quote.report_body.mr_config_id); + parse_claim!(claims, "report_data", quote.report_data()); + parse_claim!(claims, "init_data", quote.mr_config_id()); log::info!("\nParsed Evidence claims map: \n{:?}\n", &claims); diff --git a/attestation-service/verifier/src/tdx/mod.rs b/attestation-service/verifier/src/tdx/mod.rs index a8eec2157..f9edd90d9 100644 --- a/attestation-service/verifier/src/tdx/mod.rs +++ b/attestation-service/verifier/src/tdx/mod.rs @@ -60,7 +60,7 @@ async fn verify_evidence( if let ReportData::Value(expected_report_data) = expected_report_data { debug!("Check the binding of REPORT_DATA."); let expected_report_data = regularize_data(expected_report_data, 64, "REPORT_DATA", "TDX"); - if expected_report_data != quote.report_body.report_data { + if expected_report_data != quote.report_data() { bail!("REPORT_DATA is different from that in TDX Quote"); } } @@ -69,7 +69,7 @@ async fn verify_evidence( debug!("Check the binding of MRCONFIGID."); let expected_init_data_hash = regularize_data(expected_init_data_hash, 48, "MRCONFIGID", "TDX"); - if expected_init_data_hash != quote.report_body.mr_config_id { + if expected_init_data_hash != quote.mr_config_id() { bail!("MRCONFIGID is different from that in TDX Quote"); } } @@ -86,10 +86,10 @@ async fn verify_evidence( log::debug!("Get CC Eventlog. \n{}\n", &ccel.cc_events); let rtmr_from_quote = Rtmr { - rtmr0: quote.report_body.rtmr_0, - rtmr1: quote.report_body.rtmr_1, - rtmr2: quote.report_body.rtmr_2, - rtmr3: quote.report_body.rtmr_3, + rtmr0: quote.rtmr_0().try_into().expect("must be 48 bytes"), + rtmr1: quote.rtmr_1().try_into().expect("must be 48 bytes"), + rtmr2: quote.rtmr_2().try_into().expect("must be 48 bytes"), + rtmr3: quote.rtmr_3().try_into().expect("must be 48 bytes"), }; ccel.integrity_check(rtmr_from_quote)?; diff --git a/attestation-service/verifier/src/tdx/quote.rs b/attestation-service/verifier/src/tdx/quote.rs index cdf8d2bcb..e01a4f764 100644 --- a/attestation-service/verifier/src/tdx/quote.rs +++ b/attestation-service/verifier/src/tdx/quote.rs @@ -11,7 +11,7 @@ use std::time::{Duration, SystemTime}; use sgx_dcap_quoteverify_rs as qvl; -pub const QUOTE_PAYLOAD_SIZE: usize = 632; +pub const QUOTE_HEADER_SIZE: usize = 48; /// The quote header. It is designed to compatible with earlier versions of the quote. #[repr(C)] @@ -56,7 +56,7 @@ impl fmt::Display for QuoteHeader { /// SGX Report2 body #[repr(C)] #[derive(Debug, Pread)] -pub struct ReportBody { +pub struct ReportBody2 { ///< 0: TEE_TCB_SVN Array pub tcb_svn: [u8; 16], ///< 16: Measurement of the SEAM module @@ -87,7 +87,7 @@ pub struct ReportBody { pub report_data: [u8; 64], } -impl fmt::Display for ReportBody { +impl fmt::Display for ReportBody2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, @@ -126,29 +126,271 @@ impl fmt::Display for ReportBody { } } -/// TD Quote Payload(Version 4) -/// First 632 bytes of TD Quote -/// Excluding the signature data attached at the end of the Quote. -/// -/// Refer to: https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h#L141 +/// SGX Report2 body for quote v5 #[repr(C)] #[derive(Debug, Pread)] -pub struct Quote { - pub header: QuoteHeader, - pub report_body: ReportBody, +pub struct ReportBody2v15 { + ///< 0: TEE_TCB_SVN Array + pub tcb_svn: [u8; 16], + ///< 16: Measurement of the SEAM module + pub mr_seam: [u8; 48], + ///< 64: Measurement of a 3rd party SEAM module’s signer (SHA384 hash). + /// The value is 0’ed for Intel SEAM module + pub mrsigner_seam: [u8; 48], + ///< 112: MBZ: TDX 1.0 + pub seam_attributes: [u8; 8], + ///< 120: TD's attributes + pub td_attributes: [u8; 8], + ///< 128: TD's XFAM + pub xfam: [u8; 8], + ///< 136: Measurement of the initial contents of the TD + pub mr_td: [u8; 48], + ///< 184: Software defined ID for non-owner-defined configuration on + /// the guest TD. e.g., runtime or OS configuration + pub mr_config_id: [u8; 48], + ///< 232: Software defined ID for the guest TD's owner + pub mr_owner: [u8; 48], + ///< 280: Software defined ID for owner-defined configuration of the + /// guest TD, e.g., specific to the workload rather than the runtime or OS + pub mr_owner_config: [u8; 48], + ///< 328: Array of 4(TDX1: NUM_RTMRS is 4) runtime extendable + /// measurement registers + pub rtmr_0: [u8; 48], + pub rtmr_1: [u8; 48], + pub rtmr_2: [u8; 48], + pub rtmr_3: [u8; 48], + ///< 520: Additional report data + pub report_data: [u8; 64], + ///< 584: Array of TEE TCB SVNs (for TD preserving). + pub tee_tcb_svn2: [u8; 16], + ///< 600: If is one or more bound or pre-bound service TDs, SERVTD_HASH is + /// the SHA384 hash of the TDINFO_STRUCTs of those service TDs bound. + /// Else, SERVTD_HASH is 0. + pub mr_servicetd: [u8; 48], +} + +impl fmt::Display for ReportBody2v15 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "Report Body: + \n\tTCB SVN:\n\t{:X?} + \n\tMRSEAM:\n\t{:X?} + \n\tMRSIGNER_SEAM:\n\t{:X?} + \n\tSEAM Attributes:\n\t{:X?} + \n\tTD Attributes:\n\t{:X?} + \n\tTD XFAM:\n\t{:X?} + \n\tMRTD:\n\t{:X?} + \n\tMRCONFIG ID:\n\t{:X?} + \n\tMROWNER:\n\t{:X?} + \n\tMROWNER_CONFIG:\n\t{:X?} + \n\tRTMR[0]:\n\t{:X?} + \n\tRTMR[1]:\n\t{:X?} + \n\tRTMR[2]:\n\t{:X?} + \n\tRTMR[3]:\n\t{:X?} + \n\tReport Data:\n\t{:X?} + \n\tTEE TCB SVN2:\n\t{:X?} + \n\tMR SERVICETD:\n\t{:X?}", + hex::encode(self.tcb_svn), + hex::encode(self.mr_seam), + hex::encode(self.mrsigner_seam), + hex::encode(self.seam_attributes), + hex::encode(self.td_attributes), + hex::encode(self.xfam), + hex::encode(self.mr_td), + hex::encode(self.mr_config_id), + hex::encode(self.mr_owner), + hex::encode(self.mr_owner_config), + hex::encode(self.rtmr_0), + hex::encode(self.rtmr_1), + hex::encode(self.rtmr_2), + hex::encode(self.rtmr_3), + hex::encode(self.report_data), + hex::encode(self.tee_tcb_svn2), + hex::encode(self.mr_servicetd) + ) + } +} + +#[repr(u16)] +#[derive(Debug)] +pub enum QuoteV5Type { + TDX10 = 2, + TDX15 = 3, +} + +impl fmt::Display for QuoteV5Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + QuoteV5Type::TDX10 => writeln!(f, "Quote v5 Type: TDX 1.0"), + QuoteV5Type::TDX15 => writeln!(f, "Quote v5 Type: TDX 1.5"), + } + } +} + +impl QuoteV5Type { + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() < 2 { + bail!("parse QuoteV5 Type failed. Bytes length < 2 bytes"); + } + let mut r#type: [u8; 2] = [0; 2]; + r#type.copy_from_slice(&bytes[0..2]); + let r#type = u16::from_le_bytes(r#type); + let r#type = match r#type { + 2 => QuoteV5Type::TDX10, + 3 => QuoteV5Type::TDX15, + others => bail!("parse QuoteV5 Type failed. {others} not defined."), + }; + + Ok(r#type) + } + + pub fn as_bytes(&self) -> [u8; 2] { + // The unsafe here is ok as it is marked as repr(u16) + unsafe { + let raw_value: u16 = *(self as *const QuoteV5Type as *const u16); + raw_value.to_ne_bytes() + } + } +} + +pub enum QuoteV5Body { + Tdx10(ReportBody2), + Tdx15(ReportBody2v15), +} + +impl fmt::Display for QuoteV5Body { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + QuoteV5Body::Tdx10(body) => write!(f, "{}", body), + QuoteV5Body::Tdx15(body) => write!(f, "{}", body), + } + } +} + +pub enum Quote { + /// TD Quote Payload(Version 4) + /// First 632 bytes of TD Quote + /// Excluding the signature data attached at the end of the Quote. + /// + /// Refer to: https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_4.h#L141 + V4 { + header: QuoteHeader, + body: ReportBody2, + }, + + /// TD Quote Payload(Version 5) + /// First 638 bytes of TD Quote + /// Excluding the signature data attached at the end of the Quote. + /// + /// Refer to: https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_5.h#L106 + V5 { + header: QuoteHeader, + r#type: QuoteV5Type, + size: [u8; 4], + body: QuoteV5Body, + }, +} + +macro_rules! body_field { + ($r: ident) => { + pub fn $r(&self) -> &[u8] { + match self { + Quote::V4 { body, .. } => &body.$r, + Quote::V5 { body, .. } => match body { + QuoteV5Body::Tdx10(body) => &body.$r, + QuoteV5Body::Tdx15(body) => &body.$r, + }, + } + } + }; +} + +impl Quote { + body_field!(report_data); + body_field!(mr_config_id); + body_field!(rtmr_0); + body_field!(rtmr_1); + body_field!(rtmr_2); + body_field!(rtmr_3); } impl fmt::Display for Quote { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TD Quote:\n{}\n{}\n", self.header, self.report_body) + match self { + Quote::V4 { header, body } => write!(f, "TD Quote (V4):\n{header}\n{body}\n"), + Quote::V5 { + header, + r#type, + size, + body, + } => write!( + f, + "TD Quote (V5):\n{header}\n{type}\n{}\n{body}\n", + hex::encode(size) + ), + } } } pub fn parse_tdx_quote(quote_bin: &[u8]) -> Result { - let quote_body = "e_bin[..QUOTE_PAYLOAD_SIZE]; - quote_body - .pread::(0) - .map_err(|e| anyhow!("Parse TD quote failed: {:?}", e)) + let quote_header = "e_bin[..QUOTE_HEADER_SIZE]; + let header = quote_header + .pread::(0) + .map_err(|e| anyhow!("Parse TD quote header failed: {:?}", e))?; + + match header.version { + [4, 0] => { + let body: ReportBody2 = quote_bin + .pread::(QUOTE_HEADER_SIZE) + .map_err(|e| anyhow!("Parse TD quote v4 body failed: {:?}", e))?; + Ok(Quote::V4 { header, body }) + } + [5, 0] => { + let r#type = QuoteV5Type::from_bytes( + "e_bin + [QUOTE_HEADER_SIZE..QUOTE_HEADER_SIZE + std::mem::size_of::()], + )?; + let mut size: [u8; 4] = [0; 4]; + size.copy_from_slice( + "e_bin[QUOTE_HEADER_SIZE + std::mem::size_of::() + ..QUOTE_HEADER_SIZE + + std::mem::size_of::() + + std::mem::size_of::<[u8; 4]>()], + ); + match r#type { + QuoteV5Type::TDX10 => { + let offset = QUOTE_HEADER_SIZE + + std::mem::size_of::() + + std::mem::size_of::<[u8; 4]>(); + let body: ReportBody2 = quote_bin + .pread::(offset) + .map_err(|e| anyhow!("Parse TD quote v5 TDX1.0 body failed: {:?}", e))?; + Ok(Quote::V5 { + header, + r#type, + size, + body: QuoteV5Body::Tdx10(body), + }) + } + QuoteV5Type::TDX15 => { + let offset = QUOTE_HEADER_SIZE + + std::mem::size_of::() + + std::mem::size_of::<[u8; 4]>(); + let body: ReportBody2v15 = quote_bin + .pread::(offset) + .map_err(|e| anyhow!("Parse TD quote v5 TDX1.5 body failed: {:?}", e))?; + Ok(Quote::V5 { + header, + r#type, + size, + body: QuoteV5Body::Tdx15(body), + }) + } + } + } + _ => Err(anyhow!("Quote version not defined.")), + } } pub async fn ecdsa_quote_verification(quote: &[u8]) -> Result<()> { @@ -247,25 +489,34 @@ pub async fn ecdsa_quote_verification(quote: &[u8]) -> Result<()> { #[cfg(test)] mod tests { + use rstest::rstest; + use super::*; use std::fs; - #[test] - fn test_parse_tdx_quote() { - let quote_bin = fs::read("./test_data/tdx_quote_4.dat").unwrap(); + #[rstest] + #[case("./test_data/tdx_quote_4.dat")] + #[case("./test_data/tdx_quote_5.dat")] + fn test_parse_tdx_quote(#[case] quote_path: &str) { + let quote_bin = fs::read(quote_path).unwrap(); let quote = parse_tdx_quote("e_bin); assert!(quote.is_ok()); let parsed_quote = format!("{}", quote.unwrap()); - let _ = fs::write("test_data/parse_tdx_quote_output.txt", parsed_quote); + let _ = fs::write(format!("{quote_path}.txt"), parsed_quote); } + #[rstest] + #[ignore] + #[tokio::test] + #[case("./test_data/tdx_quote_4.dat")] #[ignore] #[tokio::test] - async fn test_verify_tdx_quote() { - let quote_bin = fs::read("./test_data/quote.dat").unwrap(); + #[case("./test_data/tdx_quote_5.dat")] + async fn test_verify_tdx_quote(#[case] quote: &str) { + let quote_bin = fs::read(quote).unwrap(); let res = ecdsa_quote_verification(quote_bin.as_slice()).await; - assert!(res.is_ok(), "error"); + assert!(res.is_ok(), "{res:?}"); } } diff --git a/attestation-service/verifier/test_data/tdx_quote_5.dat b/attestation-service/verifier/test_data/tdx_quote_5.dat new file mode 100644 index 0000000000000000000000000000000000000000..50512871ad0b04fd57ea174a3659a0271f1a345c GIT binary patch literal 5006 zcmcIn3zQSp8D4h**HHwubX8EON3F+IGs$Kjsr7O1%w#f2X0kJr*QAOjlk6mu$!qhN zWbpWCL9srNqtN05g;mj_m5Nq{`Z#cW0UjTvDvEk+l}Bmy)D}fcOYbDR5O>!Kc${;R z%=z#A@Bjbze&7B6Ol)awxu&J@+s}CyPjOKbLHCg z@2tM(r0d-8cKnjc>g7_=Zi_mhkU8|BU*(^CxKg zE?1vB((|F?npJb;Gu~Zx^komdoZGdVe{TIVo#ihrAMRP;d1~?E+h6POc#Qm+)91{4 ziTu~899qNK9k39GB+tzjrE&17vzuz-?Cf&Yx;oci&KJ=##FXbJt zy+GbO>9t8MPLxG!>xn0~?Q3bk@*uW-+VGt1!@nO7t$6%xeBGk+e=T}7X=uo|)xNXq zi`~~Rz~;T$J~zGL+m_tA^z18gw=L+PIs1ye#NXSdTro}l$C{@D!sK-t(8CC)VDxZrd-JtJY6kxa;1>%H-5(ue4r0u2Ylo_*7rk ze#_AEsbHZGqw{0Tpp_QQ@7Pda(}j8jgX zIk9E-u`MmelGA7}3vx6;6ljsPJ0M^QjCFx3qXGpgTo4&pI-r%~bg;-cIai2)JdYQZ z09{SS=}1M+;0ljZRaym7V}6dss1XN>tH@c1COPqF$WdkmUZ)g^4D!5-1SP)|>c%Az zk}=v@ll&CQBuxWrfWio%6XvRf0o;vMB|p%Deiqupq@TfAlCAnkVCP8I$_8`D##Wnc z7&7WINu^i<)K>($9uZNrNJv)#cwAzfkQ8f>jD+1Nvq)aDIq`^}in34{&Op(H5eMGp zsL8aWCWVE3%x14TNgy_|l3BvaC1Y73$xvKT3cHgmUqq=(B!+5aNZ=;iLe25 zMR)1wBm`VV;dN&Y1hkMNZp84IJ)r?n&IT|C+3y2E+1sV@dbBZl0MfiJsZhx|dz3H} ziAG%lF1y$sZ_SaE>2x{na$DstL5sLJ4U@Cx&IS!{rU4*thO5LxhY{&gD#%`o(^@7P z;t-IuN-X8Du{DP-*-EOM(JhjVa$xcSlw~5JZZ&2@Cy}mJF?$=6gtYj?2U_OF~i;2Jo53<>LDw80e!+jKd<(Nl>rf4|taa0!9bszNl%M z5D^!cnBC7)90qui0I8g=C`<;Sk0w$F1_4h|R6oooSvA6uf>@3WP$?r8>dq=?zSG>L z0+vjt=uQfUBu^2DnJ{1g9x6q2-UsXeVE~{!#@H1GV&e{&v{uJDpfbkTF*7nWBa9On zq6p&!fMx))5#Vbj5N3pN79z|5!w$`*5%m(r8)%Bq>_D0UM$NC6Kz>66(kx+=gIO}! z6yR$mP~$`}9Virl^n-!Xr$8w@k8nT{Kw%*OEZG0lqvo2Al0+u}P&NVc?3>D>FbJZ& zPWPF?;)YnjV^sHMnDpab-8u)Xu4HYKiDEHmXL_N~n73;^j&A7@dKX5FxS!p*LUj zRg{7=Ay&1FUvq0%!kh)xAs@*gl?@A;Tsy*{E(X&n zT<=Wv1SLAu6>wT?wsJI_z$G`SS_26z3p)KOX^p13Wr883m{kNBvb&ld@CWmioIQ}M zr9`PZNQS(bfM6#W2j{5`^mCoxfxD_ z=(=<)N*?IgP=~j_VQX}F?nt_t}!}-%zAL>m1&nqhjdd~MK`s>2!^ zz8&j)6%mI8g-HTm$kNTHg-+2yq(oBYayi{w?iakp5Ita#QoXbocGyw(?$;G0&J?h_ sac$6*V~d^PTzAe=4EOjPe5mRYKqV5OeQ|;Bl`91y94#>aPj6fP2S#quUH||9 literal 0 HcmV?d00001 From 1364fc71382fdd6d43b8e1255eaf3b51785f6b6d Mon Sep 17 00:00:00 2001 From: Xynnn007 Date: Fri, 22 Mar 2024 15:10:51 +0800 Subject: [PATCH 2/2] AS/docs: update parsed claims docs for tdx quote v5 Signed-off-by: Xynnn007 --- attestation-service/docs/parsed_claims.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/attestation-service/docs/parsed_claims.md b/attestation-service/docs/parsed_claims.md index b783fcfdb..4b2411cc8 100644 --- a/attestation-service/docs/parsed_claims.md +++ b/attestation-service/docs/parsed_claims.md @@ -24,7 +24,7 @@ The following fields are optional. Whether they appear depends on whether there - `tdx.ccel.kernel_parameters.*`: different kernel parameter items. For example `console=hvc0` will be parsed into a claim `"tdx.ccel.kernel_parameters.console": "hvc0"`. `rw` will be parsed into a claim `"tdx.ccel.kernel_parameters.rw": null`. The following fields always exist. -- `tdx.quote.header.version`: for TDX this field is always 4. +- `tdx.quote.header.version`: The quote format version. Now supports 4 and 5. - `tdx.quote.header.att_key_type`: enum of the algorithm used in signature. - `tdx.quote.header.tee_type`: TDX is always 0x81. - `tdx.quote.header.reserved`: reserved. @@ -45,6 +45,10 @@ The following fields always exist. - `tdx.quote.body.rtmr_1`: Runtime measurement register 1. - `tdx.quote.body.rtmr_2`: Runtime measurement register 2. - `tdx.quote.body.rtmr_3`: Runtime measurement register 3. +- `tdx.quote.type`: Indicating quote v5 type. 2 means TDX 1.0 quote and 3 means TDX 1.5 quote. Only quote format V5 contains this field. +- `tdx.quote.size`: Quote body length. Only quote format V5 contains this field. +- `tdx.quote.body.tee_tcb_svn2`: Array of TEE TCB SVNs (for TD preserving). +- `tdx.quote.body.mr_servicetd`: If there is one or more bound or pre-bound service TDs, this field is the SHA384 hash of the `TDINFO`s of those service TDs bound. Else, this field is 0. ## Intel SGX