Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AA/attester: support to read CCEL for kernel older than v6.4 #860

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion attestation-agent/attester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ all-attesters = [
# quotes. It's an unconditional dependency for tdx-attester since that is the only 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", "tokio/io-util"]
sgx-attester = ["occlum_dcap"]
az-snp-vtpm-attester = ["az-snp-vtpm"]
az-tdx-vtpm-attester = ["az-snp-vtpm-attester", "az-tdx-vtpm"]
Expand Down
101 changes: 101 additions & 0 deletions attestation-agent/attester/src/tdx/ccel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright (c) 2024 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use anyhow::{bail, Context};
use scroll::Pread;
use tokio::io::{AsyncReadExt, AsyncSeekExt};

use crate::tdx::TdxAttester;

use std::path::Path;

const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL";

/// Path to the ACPI table CCEL description
const CCEL_ACPI_DESCRIPTION: &str = "/sys/firmware/acpi/tables/CCEL";

/// Guest memory which is used to read the CCEL
const GUEST_MEMORY: &str = "/dev/mem";

/// Signature of CCEL's ACPI Description Header
const CCEL_SIGNATURE: &[u8] = b"CCEL";

#[repr(C)]
#[derive(Pread)]
struct EfiAcpiDescriptionHeader {
signature: u32,
length: u32,
revision: u8,
checksum: u8,
oem_id: [u8; 6],
oem_table_id: u64,
oem_revision: u32,
craetor_id: u32,
creator_revision: u32,
}

#[repr(C)]
#[derive(Pread)]
struct TdxEventLogACPITable {
efi_acpi_description_header: EfiAcpiDescriptionHeader,
rsv: u32,
laml: u64,
lasa: u64,
}

impl TdxAttester {
pub async fn read_ccel() -> anyhow::Result<Vec<u8>> {
if Path::new(CCEL_PATH).exists() {
let ccel = tokio::fs::read(CCEL_PATH).await?;
return Ok(ccel);
}

let efi_acpi_description = tokio::fs::read(CCEL_ACPI_DESCRIPTION)
.await
.context("read ccel description")?;
let ccel_acpi_table = efi_acpi_description
.pread::<TdxEventLogACPITable>(0)
.context("parse CCEL ACPI description failed")?;

let ccel_signature = u32::from_le_bytes(CCEL_SIGNATURE.try_into()?);
if ccel_acpi_table.efi_acpi_description_header.signature != ccel_signature {
bail!("invalid CCEL ACPI table: wrong CCEL signature");
}

if ccel_acpi_table.rsv != 0 {
bail!("invalid CCEL ACPI table: RSV must be 0");
}

if ccel_acpi_table.efi_acpi_description_header.length != efi_acpi_description.len() as u32 {
bail!("invalid CCEL ACPI table: header length not match");
}

let mut guest_memory = tokio::fs::OpenOptions::new()
.read(true)
.open(GUEST_MEMORY)
.await?;
guest_memory
.seek(std::io::SeekFrom::Start(ccel_acpi_table.lasa))
.await?;
let mut ccel = vec![0; ccel_acpi_table.laml as usize];
let read_size = guest_memory.read(&mut ccel).await?;
if read_size == 0 {
bail!("read CCEL failed");
}

Ok(ccel)
}
}

#[cfg(test)]
mod tests {
use crate::tdx::TdxAttester;

#[ignore]
#[tokio::test]
async fn test_read_ccel() {
let _ccel = TdxAttester::read_ccel().await.unwrap();
}
}
4 changes: 2 additions & 2 deletions attestation-agent/attester/src/tdx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use std::fs;
use std::path::Path;
use tdx_attest_rs::tdx_report_t;

mod ccel;
mod report;
mod rtmr;

const TDX_REPORT_DATA_SIZE: usize = 64;
const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL";

pub fn detect_platform() -> bool {
TsmReportPath::new(TsmReportProvider::Tdx).is_ok() || Path::new("/dev/tdx_guest").exists()
Expand Down Expand Up @@ -129,7 +129,7 @@ impl Attester for TdxAttester {
let engine = base64::engine::general_purpose::STANDARD;
let quote = engine.encode(quote_bytes);

let cc_eventlog = match std::fs::read(CCEL_PATH) {
let cc_eventlog = match Self::read_ccel().await {
Result::Ok(el) => Some(engine.encode(el)),
Result::Err(e) => {
log::warn!("Read CC Eventlog failed: {:?}", e);
Expand Down
Loading