From d02b5527cfb80686d1c947826ddee9463ae96c3b Mon Sep 17 00:00:00 2001 From: Mikko Ylinen Date: Wed, 12 Feb 2025 13:27:08 +0200 Subject: [PATCH 1/4] attester: tdx: use iocuddle to get TD Report TDX Guest driver support is problematic: configfs-tsm currently does not allow to request bare TD reports. It's always a signed TD quote that needs exits to QGS for signing. However, for the initdata checks, we only need the TD report. Linux still supports the /dev/tdx_guest ioctl() for getting the report. Since the early days, we have used libtdx-attest wrappers for the ioctls(). However, getting the C libraries and headers installed in various places has turned out to be problematic. Furthermore, it isn't even necessary for uses cases like kbs-client (where only the configfs-tsm GetQuote is needed). Move the get_report() method to use raw ioctls() using iocuddle. This follows the sev crate implementation and which turns out to be very simple to adopt here too. Signed-off-by: Mikko Ylinen --- Cargo.lock | 1 + attestation-agent/attester/Cargo.toml | 5 ++- attestation-agent/attester/src/tdx/mod.rs | 51 ++++++++++++++++------- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 518b2da62..43e009188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -382,6 +382,7 @@ dependencies = [ "hex", "hyper 0.14.28", "hyper-tls 0.5.0", + "iocuddle", "kbs-types", "log", "occlum_dcap", diff --git a/attestation-agent/attester/Cargo.toml b/attestation-agent/attester/Cargo.toml index 9c1459e11..9c5df16b3 100644 --- a/attestation-agent/attester/Cargo.toml +++ b/attestation-agent/attester/Cargo.toml @@ -14,6 +14,7 @@ az-tdx-vtpm = { version = "0.7.0", default-features = false, features = ["attest base64.workspace = true clap = { workspace = true, features = ["derive"], optional = true } hex.workspace = true +iocuddle = { version = "0.1.1", optional = true } kbs-types.workspace = true log.workspace = true occlum_dcap = { git = "https://github.com/occlum/occlum", tag = "v0.29.7", optional = true } @@ -57,10 +58,10 @@ all-attesters = [ ] # tsm-report enables a module that helps attesters to use Linux TSM_REPORTS for generating -# quotes. It's an unconditional dependency for tdx-attester since that is the only way to +# quotes. It's an unconditional dependency for tdx-attester since that is the preferred way to # generate TDX quotes with upstream kernels. tsm-report = ["tempfile"] -tdx-attester = ["scroll", "tsm-report", "tdx-attest-rs"] +tdx-attester = ["scroll", "tsm-report", "tdx-attest-rs", "iocuddle"] sgx-attester = ["occlum_dcap"] az-snp-vtpm-attester = ["az-snp-vtpm"] az-tdx-vtpm-attester = ["az-snp-vtpm-attester", "az-tdx-vtpm"] diff --git a/attestation-agent/attester/src/tdx/mod.rs b/attestation-agent/attester/src/tdx/mod.rs index 70507876d..34a300dc5 100644 --- a/attestation-agent/attester/src/tdx/mod.rs +++ b/attestation-agent/attester/src/tdx/mod.rs @@ -11,21 +11,21 @@ use crate::utils::pad; use crate::InitDataResult; use anyhow::*; use base64::Engine; +use iocuddle::{Group, Ioctl, WriteRead}; use report::TdReport; use scroll::Pread; use serde::{Deserialize, Serialize}; -use std::fs; use std::path::Path; -use tdx_attest_rs::tdx_report_t; mod report; mod rtmr; const TDX_REPORT_DATA_SIZE: usize = 64; const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL"; +const TDX_GUEST_IOCTL: &str = "/dev/tdx_guest"; pub fn detect_platform() -> bool { - TsmReportPath::new(TsmReportProvider::Tdx).is_ok() || Path::new("/dev/tdx_guest").exists() + TsmReportPath::new(TsmReportProvider::Tdx).is_ok() || Path::new(TDX_GUEST_IOCTL).exists() } fn get_quote_ioctl(report_data: &Vec) -> Result> { @@ -72,20 +72,34 @@ struct TdxEvidence { #[derive(Debug, Default)] pub struct TdxAttester {} +#[repr(C)] +struct TdxReportReq { + report_data: [u8; 64], + + d: [u8; 1024], +} + +impl Default for TdxReportReq { + fn default() -> Self { + Self { + report_data: [0; 64], + d: [0; 1024], + } + } +} + +const TDX: Group = Group::new(b'T'); +const TDX_CMD_GET_REPORT0: Ioctl = unsafe { TDX.write_read(0x1) }; + impl TdxAttester { fn get_report() -> Result { - let mut report = tdx_report_t { d: [0; 1024] }; - match tdx_attest_rs::tdx_att_get_report(None, &mut report) { - tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => { - log::debug!("Successfully got report") - } - error_code => { - bail!( - "TDX Attester: Failed to get TD report. Error code: {:?}", - error_code - ); - } - }; + let mut report = TdxReportReq::default(); + let mut fd = + std::fs::File::open(TDX_GUEST_IOCTL).context("Open TD report ioctl() failed")?; + + TDX_CMD_GET_REPORT0 + .ioctl(&mut fd, &mut report) + .context("Get TD report ioctl() failed")?; let td_report = report .d @@ -137,7 +151,7 @@ impl Attester for TdxAttester { } }; - let aa_eventlog = match fs::read_to_string(DEFAULT_EVENTLOG_PATH) { + let aa_eventlog = match std::fs::read_to_string(DEFAULT_EVENTLOG_PATH) { Result::Ok(el) => Some(el), Result::Err(e) => { log::warn!("Read AA Eventlog failed: {:?}", e); @@ -217,4 +231,9 @@ mod tests { let evidence = attester.get_evidence(report_data).await; assert!(evidence.is_ok()); } + #[ignore] + #[tokio::test] + async fn test_tdx_get_report() { + assert!(TdxAttester::get_report().is_ok()); + } } From f08db86ab24bf898dd4319946785083a21c2cad1 Mon Sep 17 00:00:00 2001 From: Mikko Ylinen Date: Wed, 12 Feb 2025 13:35:37 +0200 Subject: [PATCH 2/4] tdx-attester: make tdx-attest dependency opt-in For the use-cases needed by CoCo and supported by upstream Linux, we don't need libtdx-attest so make the dependency a build-time opt-in feature. Signed-off-by: Mikko Ylinen --- Cargo.lock | 1 + attestation-agent/attester/Cargo.toml | 4 +- attestation-agent/attester/src/tdx/mod.rs | 45 +++++++++++++++-------- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43e009188..c799f71ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,6 +376,7 @@ dependencies = [ "az-snp-vtpm", "az-tdx-vtpm", "base64 0.22.1", + "cfg-if", "clap 4.2.7", "codicon", "csv-rs", diff --git a/attestation-agent/attester/Cargo.toml b/attestation-agent/attester/Cargo.toml index 9c5df16b3..5cb2c3172 100644 --- a/attestation-agent/attester/Cargo.toml +++ b/attestation-agent/attester/Cargo.toml @@ -13,6 +13,7 @@ az-snp-vtpm = { version = "0.7.1", default-features = false, features = ["attest az-tdx-vtpm = { version = "0.7.0", default-features = false, features = ["attester"], optional = true } base64.workspace = true clap = { workspace = true, features = ["derive"], optional = true } +cfg-if.workspace = true hex.workspace = true iocuddle = { version = "0.1.1", optional = true } kbs-types.workspace = true @@ -61,7 +62,8 @@ all-attesters = [ # quotes. It's an unconditional dependency for tdx-attester since that is the preferred way to # generate TDX quotes with upstream kernels. tsm-report = ["tempfile"] -tdx-attester = ["scroll", "tsm-report", "tdx-attest-rs", "iocuddle"] +tdx-attester = ["scroll", "tsm-report", "iocuddle"] +tdx-attest-dcap-ioctls = ["tdx-attest-rs"] sgx-attester = ["occlum_dcap"] az-snp-vtpm-attester = ["az-snp-vtpm"] az-tdx-vtpm-attester = ["az-snp-vtpm-attester", "az-tdx-vtpm"] diff --git a/attestation-agent/attester/src/tdx/mod.rs b/attestation-agent/attester/src/tdx/mod.rs index 34a300dc5..daca6dd3d 100644 --- a/attestation-agent/attester/src/tdx/mod.rs +++ b/attestation-agent/attester/src/tdx/mod.rs @@ -3,8 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 // -use self::rtmr::TdxRtmrEvent; - use super::tsm_report::*; use super::Attester; use crate::utils::pad; @@ -28,19 +26,26 @@ pub fn detect_platform() -> bool { TsmReportPath::new(TsmReportProvider::Tdx).is_ok() || Path::new(TDX_GUEST_IOCTL).exists() } -fn get_quote_ioctl(report_data: &Vec) -> Result> { - let tdx_report_data = tdx_attest_rs::tdx_report_data_t { - // report_data.resize() ensures copying report_data to - // tdx_attest_rs::tdx_report_data_t cannot panic. - d: report_data.as_slice().try_into().unwrap(), - }; - - match tdx_attest_rs::tdx_att_get_quote(Some(&tdx_report_data), None, None, 0) { - (tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS, Some(q)) => Ok(q), - (error_code, _) => Err(anyhow!( - "TDX getquote ioctl: failed with error code: {:?}", - error_code - )), +#[allow(unused_variables)] +fn get_quote_ioctl(report_data: &[u8]) -> Result> { + cfg_if::cfg_if! { + if #[cfg(feature = "tdx-attest-dcap-ioctls")] { + let tdx_report_data = tdx_attest_rs::tdx_report_data_t { + // report_data.resize() ensures copying report_data to + // tdx_attest_rs::tdx_report_data_t cannot panic. + d: report_data.as_slice().try_into().unwrap(), + }; + + match tdx_attest_rs::tdx_att_get_quote(Some(&tdx_report_data), None, None, 0) { + (tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS, Some(q)) => Ok(q), + (error_code, _) => Err(anyhow!( + "TDX DCAP get_quote: failed with error code: {:?}", + error_code + )), + } + } else { + Err(anyhow!("TDX DCAP ioctls: support not available")) + } } } @@ -180,11 +185,19 @@ impl Attester for TdxAttester { let rtmr_index = Self::pcr_to_rtmr(register_index); let extend_data: [u8; 48] = pad(&event_digest); - let event: Vec = TdxRtmrEvent::default() + + log::debug!( + "TDX Attester: extend RTRM{rtmr_index}: {}", + hex::encode(extend_data) + ); + + #[cfg(feature = "tdx-attest-dcap-ioctls")] + let event: Vec = rtmr::TdxRtmrEvent::default() .with_extend_data(extend_data) .with_rtmr_index(rtmr_index) .into(); + #[cfg(feature = "tdx-attest-dcap-ioctls")] match tdx_attest_rs::tdx_att_extend(&event) { tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => { log::debug!("TDX extend runtime measurement succeeded.") From f21b81b4888a2fae7e26993763c838ed7b35321e Mon Sep 17 00:00:00 2001 From: Mikko Ylinen Date: Fri, 14 Feb 2025 09:34:29 +0200 Subject: [PATCH 3/4] attestation-agent: add customized tdx-attester For configurations where the out-of-tree RTMR extend ioctl() is available and/or the libtdx-attest supported way to get the TD quote is needed, add a customized tdx-attester feature that provides this. This new feature is disabled by default. Signed-off-by: Mikko Ylinen --- attestation-agent/README.md | 1 + attestation-agent/attestation-agent/Cargo.toml | 1 + attestation-agent/kbc/Cargo.toml | 1 + attestation-agent/kbs_protocol/Cargo.toml | 1 + 4 files changed, 4 insertions(+) diff --git a/attestation-agent/README.md b/attestation-agent/README.md index f936a0082..5c3e1a4ba 100644 --- a/attestation-agent/README.md +++ b/attestation-agent/README.md @@ -113,6 +113,7 @@ AA supports different kinds of hardware TEE attesters, now | Attester name | Info | | ------------------- | -------------------------- | | tdx-attester | Intel TDX | +| tdx-attester-libtdx | Intel TDX (using libtdx-attest for certain non-upstream Linux `ioctl()`s). Disabled by default. | | sgx-attester | Intel SGX DCAP | | snp-attester | AMD SEV-SNP | | az-snp-vtpm-attester| Azure SEV-SNP CVM | diff --git a/attestation-agent/attestation-agent/Cargo.toml b/attestation-agent/attestation-agent/Cargo.toml index 795788383..c3a74d3b6 100644 --- a/attestation-agent/attestation-agent/Cargo.toml +++ b/attestation-agent/attestation-agent/Cargo.toml @@ -76,6 +76,7 @@ all-attesters = [ "cca-attester", ] tdx-attester = ["kbs_protocol?/tdx-attester", "attester/tdx-attester"] +tdx-attester-libtdx = ["kbs_protocol?/tdx-attester-libtdx", "attester/tdx-attester", "attester/tdx-attest-dcap-ioctls"] sgx-attester = ["kbs_protocol?/sgx-attester", "attester/sgx-attester"] az-snp-vtpm-attester = [ "kbs_protocol?/az-snp-vtpm-attester", diff --git a/attestation-agent/kbc/Cargo.toml b/attestation-agent/kbc/Cargo.toml index 3c2d82b56..bb7f9b551 100644 --- a/attestation-agent/kbc/Cargo.toml +++ b/attestation-agent/kbc/Cargo.toml @@ -39,6 +39,7 @@ default = ["sample_kbc", "rust-crypto"] cc_kbc = ["kbs_protocol/background_check"] all-attesters = ["kbs_protocol?/all-attesters"] tdx-attester = ["kbs_protocol/tdx-attester"] +tdx-attester-libtdx = ["kbs_protocol/tdx-attester-libtdx"] sgx-attester = ["kbs_protocol/sgx-attester"] az-snp-vtpm-attester= ["kbs_protocol/az-snp-vtpm-attester"] az-tdx-vtpm-attester= ["kbs_protocol/az-tdx-vtpm-attester"] diff --git a/attestation-agent/kbs_protocol/Cargo.toml b/attestation-agent/kbs_protocol/Cargo.toml index 5dec15886..b75b73da5 100644 --- a/attestation-agent/kbs_protocol/Cargo.toml +++ b/attestation-agent/kbs_protocol/Cargo.toml @@ -53,6 +53,7 @@ aa_ttrpc = ["ttrpc-codegen", "passport", "ttrpc/async", "protobuf"] background_check = ["tokio/time"] all-attesters = ["attester/all-attesters"] tdx-attester = ["attester/tdx-attester"] +tdx-attester-libtdx = ["attester/tdx-attester", "attester/tdx-attest-dcap-ioctls"] sgx-attester = ["attester/sgx-attester"] az-snp-vtpm-attester = ["attester/az-snp-vtpm-attester"] az-tdx-vtpm-attester = ["attester/az-tdx-vtpm-attester"] From 598a3059f81f8166d2d97b29fb8d286f8e2ba5c0 Mon Sep 17 00:00:00 2001 From: Mikko Ylinen Date: Wed, 12 Feb 2025 14:21:09 +0200 Subject: [PATCH 4/4] ci: drop libtdx-attest installation Signed-off-by: Mikko Ylinen --- .github/actions/install-intel-dcap/action.yml | 15 --------------- .github/workflows/aa_basic.yml | 5 ----- .github/workflows/aa_cc_kbc.yml | 5 ----- .github/workflows/image_rs_build.yml | 5 ----- .github/workflows/publish-artifacts.yml | 5 ----- .github/workflows/trustee-attester.yml | 5 ----- 6 files changed, 40 deletions(-) delete mode 100644 .github/actions/install-intel-dcap/action.yml diff --git a/.github/actions/install-intel-dcap/action.yml b/.github/actions/install-intel-dcap/action.yml deleted file mode 100644 index 1e08af3d1..000000000 --- a/.github/actions/install-intel-dcap/action.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: 'Install Intel DCAP libraries' -inputs: - ubuntu-version: - required: true -runs: - using: "composite" - steps: - - name: Install TDX dependencies - id: install-tdx-dependencies - shell: bash - run: | - curl -sL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo gpg --dearmor --output /usr/share/keyrings/intel-sgx.gpg - echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu ${{ inputs.ubuntu-version }} main' | sudo tee /etc/apt/sources.list.d/intel-sgx.list - sudo apt-get update - sudo apt-get install -y --no-install-recommends libtdx-attest-dev diff --git a/.github/workflows/aa_basic.yml b/.github/workflows/aa_basic.yml index ab0b055a5..9a4b95810 100644 --- a/.github/workflows/aa_basic.yml +++ b/.github/workflows/aa_basic.yml @@ -72,11 +72,6 @@ jobs: run: | sudo apt-get update && sudo apt-get install -y protobuf-compiler - - uses: ./.github/actions/install-intel-dcap - with: - ubuntu-version: noble - if: matrix.instance == 'ubuntu-24.04' - - name: Install TPM dependencies run: | sudo apt-get update diff --git a/.github/workflows/aa_cc_kbc.yml b/.github/workflows/aa_cc_kbc.yml index e968a9380..c35edd357 100644 --- a/.github/workflows/aa_cc_kbc.yml +++ b/.github/workflows/aa_cc_kbc.yml @@ -69,11 +69,6 @@ jobs: override: true components: rustfmt, clippy - - uses: ./.github/actions/install-intel-dcap - with: - ubuntu-version: noble - if: matrix.instance == 'ubuntu-24.04' - - name: Install TPM dependencies run: | sudo apt-get update diff --git a/.github/workflows/image_rs_build.yml b/.github/workflows/image_rs_build.yml index 427ce0995..4dcaea625 100644 --- a/.github/workflows/image_rs_build.yml +++ b/.github/workflows/image_rs_build.yml @@ -67,11 +67,6 @@ jobs: run: | sudo apt install -y clang llvm pkg-config nettle-dev protobuf-compiler libprotobuf-dev - - uses: ./.github/actions/install-intel-dcap - with: - ubuntu-version: noble - if: matrix.instance == 'ubuntu-24.04' - - name: Install TPM dependencies run: | sudo apt-get update diff --git a/.github/workflows/publish-artifacts.yml b/.github/workflows/publish-artifacts.yml index 29b2a91f7..68c3b1513 100644 --- a/.github/workflows/publish-artifacts.yml +++ b/.github/workflows/publish-artifacts.yml @@ -62,11 +62,6 @@ jobs: sudo apt-get update sudo apt-get install -y --no-install-recommends libtss2-dev - - uses: ./.github/actions/install-intel-dcap - with: - ubuntu-version: noble - if: matrix.platform.tee == 'tdx' - - uses: actions/checkout@v4 - name: Build diff --git a/.github/workflows/trustee-attester.yml b/.github/workflows/trustee-attester.yml index 25f319600..4d7759652 100644 --- a/.github/workflows/trustee-attester.yml +++ b/.github/workflows/trustee-attester.yml @@ -61,11 +61,6 @@ jobs: run: | sudo apt-get update && sudo apt-get install -y protobuf-compiler - - uses: ./.github/actions/install-intel-dcap - with: - ubuntu-version: noble - if: matrix.instance == 'ubuntu-24.04' - - name: Install TPM dependencies run: | sudo apt-get update