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 diff --git a/Cargo.lock b/Cargo.lock index 518b2da62..c799f71ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,12 +376,14 @@ dependencies = [ "az-snp-vtpm", "az-tdx-vtpm", "base64 0.22.1", + "cfg-if", "clap 4.2.7", "codicon", "csv-rs", "hex", "hyper 0.14.28", "hyper-tls 0.5.0", + "iocuddle", "kbs-types", "log", "occlum_dcap", 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/attester/Cargo.toml b/attestation-agent/attester/Cargo.toml index 9c1459e11..5cb2c3172 100644 --- a/attestation-agent/attester/Cargo.toml +++ b/attestation-agent/attester/Cargo.toml @@ -13,7 +13,9 @@ 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 log.workspace = true occlum_dcap = { git = "https://github.com/occlum/occlum", tag = "v0.29.7", optional = true } @@ -57,10 +59,11 @@ 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", "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 70507876d..daca6dd3d 100644 --- a/attestation-agent/attester/src/tdx/mod.rs +++ b/attestation-agent/attester/src/tdx/mod.rs @@ -3,44 +3,49 @@ // SPDX-License-Identifier: Apache-2.0 // -use self::rtmr::TdxRtmrEvent; - use super::tsm_report::*; use super::Attester; 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> { - 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")) + } } } @@ -72,20 +77,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 +156,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); @@ -166,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.") @@ -217,4 +244,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()); + } } 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"]