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: Add API of CheckInitData #462

Merged
merged 2 commits into from
Feb 2, 2024
Merged
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
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 60 additions & 2 deletions attestation-agent/app/src/rpc/attestation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ pub mod grpc {
AttestationAgentService, AttestationAgentServiceServer,
};
use attestation::{
ExtendRuntimeMeasurementRequest, ExtendRuntimeMeasurementResponse, GetEvidenceRequest,
GetEvidenceResponse, GetTokenRequest, GetTokenResponse,
CheckInitDataRequest, CheckInitDataResponse, ExtendRuntimeMeasurementRequest,
ExtendRuntimeMeasurementResponse, GetEvidenceRequest, GetEvidenceResponse, GetTokenRequest,
GetTokenResponse,
};
use std::net::SocketAddr;
use tonic::{transport::Server, Request, Response, Status};
Expand Down Expand Up @@ -116,6 +117,35 @@ pub mod grpc {

Result::Ok(Response::new(reply))
}

async fn check_init_data(
&self,
request: Request<CheckInitDataRequest>,
) -> Result<Response<CheckInitDataResponse>, Status> {
let request = request.into_inner();

let attestation_agent_mutex_clone = Arc::clone(&ASYNC_ATTESTATION_AGENT);
let mut attestation_agent = attestation_agent_mutex_clone.lock().await;

debug!("Call AA to check init data ...");

attestation_agent
.check_init_data(&request.digest)
.await
.map_err(|e| {
error!("Call AA to check init data failed: {}", e);
Status::internal(format!(
"[ERROR:{}] AA check init data failed: {}",
AGENT_NAME, e
))
})?;

debug!("Check init data successfully!");

let reply = CheckInitDataResponse {};

Result::Ok(Response::new(reply))
}
}

pub async fn start_grpc_service(socket: SocketAddr) -> Result<()> {
Expand Down Expand Up @@ -236,6 +266,34 @@ pub mod ttrpc {
let reply = attestation_agent::ExtendRuntimeMeasurementResponse::new();
::ttrpc::Result::Ok(reply)
}

async fn check_init_data(
&self,
_ctx: &::ttrpc::r#async::TtrpcContext,
req: attestation_agent::CheckInitDataRequest,
) -> ::ttrpc::Result<attestation_agent::CheckInitDataResponse> {
debug!("Call AA to check initdata ...");

let attestation_agent_mutex_clone = ASYNC_ATTESTATION_AGENT.clone();
let mut attestation_agent = attestation_agent_mutex_clone.lock().await;

attestation_agent
.check_init_data(&req.Digest)
.await
.map_err(|e| {
error!("Call AA to check initdata failed: {}", e);
let mut error_status = ::ttrpc::proto::Status::new();
error_status.set_code(Code::INTERNAL);
error_status.set_message(format!(
"[ERROR:{}] AA check initdata failed: {}",
AGENT_NAME, e
));
::ttrpc::Error::RpcStatus(error_status)
})?;

let reply = attestation_agent::CheckInitDataResponse::new();
::ttrpc::Result::Ok(reply)
}
}

pub fn start_ttrpc_service() -> Result<HashMap<String, Service>> {
Expand Down
4 changes: 3 additions & 1 deletion attestation-agent/attester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ kbs-types.workspace = true
log.workspace = true
nix = { version = "0.26.2", optional = true }
occlum_dcap = { git = "https://github.com/occlum/occlum", tag = "v0.29.7", optional = true }
scroll = { version = "0.11.0", default-features = false, features = ["derive"], optional = true }
serde.workspace = true
serde_json.workspace = true
sev = { version = "1.2.0", default-features = false, features = [
"snp",
], optional = true }
strum.workspace = true
tdx-attest-rs = { git = "https://github.com/intel/SGXDataCenterAttestationPrimitives", tag = "DCAP_1.16", optional = true }
thiserror.workspace = true
# TODO: change it to "0.1", once released.
csv-rs = { git = "https://github.com/openanolis/csv-rs", rev = "b74aa8c", optional = true }
codicon = { version = "3.0", optional = true }
Expand All @@ -52,7 +54,7 @@ all-attesters = [
"cca-attester",
]

tdx-attester = ["tdx-attest-rs"]
tdx-attester = ["scroll", "tdx-attest-rs"]
sgx-attester = ["occlum_dcap"]
az-snp-vtpm-attester = ["az-snp-vtpm"]
az-tdx-vtpm-attester = ["az-tdx-vtpm"]
Expand Down
5 changes: 5 additions & 0 deletions attestation-agent/attester/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use anyhow::*;
use kbs_types::Tee;

pub mod sample;
pub mod utils;

#[cfg(feature = "az-snp-vtpm-attester")]
pub mod az_snp_vtpm;
Expand Down Expand Up @@ -74,6 +75,10 @@ pub trait Attester {
) -> Result<()> {
bail!("Unimplemented")
}

async fn check_init_data(&self, _init_data: &[u8]) -> Result<()> {
bail!("Unimplemented");
}
}

// Detect which TEE platform the KBC running environment is.
Expand Down
24 changes: 24 additions & 0 deletions attestation-agent/attester/src/snp/hostdata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2024 Microsoft Corporation
// Copyright (c) 2024 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use thiserror::Error;

#[derive(Error, Debug)]
pub enum GetHostDataError {
#[error("Open Sev guest firmware failed: {0}")]
OpenSevGuestFirmware(#[from] std::io::Error),

#[error("Get report failed: {0}")]
GetReportError(#[from] sev::error::UserApiError),
}

pub fn get_snp_host_data() -> Result<[u8; 32], GetHostDataError> {
let mut firmware = sev::firmware::guest::Firmware::open()?;
let report_data: [u8; 64] = [0; 64];
let report = firmware.get_report(None, Some(report_data), Some(0))?;

Ok(report.host_data)
}
14 changes: 14 additions & 0 deletions attestation-agent/attester/src/snp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// SPDX-License-Identifier: Apache-2.0
//

use crate::utils::pad;

use super::Attester;
use anyhow::*;
use serde::{Deserialize, Serialize};
Expand All @@ -11,6 +13,8 @@ use sev::firmware::guest::Firmware;
use sev::firmware::host::CertTableEntry;
use std::path::Path;

mod hostdata;

pub fn detect_platform() -> bool {
Path::new("/sys/devices/platform/sev-guest").exists()
}
Expand Down Expand Up @@ -47,4 +51,14 @@ impl Attester for SnpAttester {

serde_json::to_string(&evidence).context("Serialize SNP evidence failed")
}

async fn check_init_data(&self, init_data: &[u8]) -> Result<()> {
Xynnn007 marked this conversation as resolved.
Show resolved Hide resolved
let hostdata = hostdata::get_snp_host_data().context("Get HOSTDATA failed")?;
let init_data: [u8; 32] = pad(init_data);
if init_data != hostdata {
bail!("HOSTDATA does not match.");
}

Ok(())
}
}
35 changes: 34 additions & 1 deletion attestation-agent/attester/src/tdx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
// SPDX-License-Identifier: Apache-2.0
//

use crate::utils::pad;

use super::Attester;
use anyhow::*;
use base64::Engine;
use log::debug;
use scroll::Pread;
use serde::{Deserialize, Serialize};
use std::path::Path;
use tdx_attest_rs;
use tdx_attest_rs::{self, tdx_report_t};

mod report;

const TDX_REPORT_DATA_SIZE: usize = 64;
const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL";
Expand Down Expand Up @@ -90,6 +96,33 @@ impl Attester for TdxAttester {

Ok(())
}

async fn check_init_data(&self, init_data: &[u8]) -> 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 => {
debug!("Successfully get report")
}
error_code => {
bail!(
"TDX Attester: Failed to get TD report. Error code: {:?}",
error_code
);
}
};

let td_report = report
.d
.pread::<report::TdReport>(0)
.map_err(|e| anyhow!("Parse TD report failed: {:?}", e))?;

let init_data: [u8; 48] = pad(init_data);
if init_data != td_report.tdinfo.mrconfigid {
bail!("Init data does not match!");
}

Ok(())
}
}

#[cfg(test)]
Expand Down
99 changes: 99 additions & 0 deletions attestation-agent/attester/src/tdx/report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) 2024 Microsoft Corporation
// Copyright (c) 2024 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use scroll::Pread;

#[repr(C)]
#[derive(Pread)]
/// Type header of TDREPORT_STRUCT.
pub struct TdTransportType {
/// Type of the TDREPORT (0 - SGX, 81 - TDX, rest are reserved).
pub type_: u8,

/// Subtype of the TDREPORT (Default value is 0).
pub sub_type: u8,

/// TDREPORT version (Default value is 0).
pub version: u8,

/// Added for future extension.
pub reserved: u8,
}

#[repr(C)]
#[derive(Pread)]
/// TDX guest report data, MAC and TEE hashes.
pub struct ReportMac {
/// TDREPORT type header.
pub type_: TdTransportType,

/// Reserved for future extension.
pub reserved1: [u8; 12],

/// CPU security version.
pub cpu_svn: [u8; 16],

/// SHA384 hash of TEE TCB INFO.
pub tee_tcb_info_hash: [u8; 48],

/// SHA384 hash of TDINFO_STRUCT.
pub tee_td_info_hash: [u8; 48],

/// User defined unique data passed in TDG.MR.REPORT request.
pub reportdata: [u8; 64],

/// Reserved for future extension.
pub reserved2: [u8; 32],

/// CPU MAC ID.
pub mac: [u8; 32],
}

#[repr(C)]
#[derive(Pread)]
/// TDX guest measurements and configuration.
pub struct TdInfo {
/// TDX Guest attributes (like debug, spet_disable, etc).
pub attr: [u8; 8],

/// Extended features allowed mask.
pub xfam: u64,

/// Build time measurement register.
pub mrtd: [u64; 6],

/// Software-defined ID for non-owner-defined configuration of the guest - e.g., run-time or OS configuration.
pub mrconfigid: [u8; 48],

/// Software-defined ID for the guest owner.
pub mrowner: [u64; 6],

/// Software-defined ID for owner-defined configuration of the guest - e.g., specific to the workload.
pub mrownerconfig: [u64; 6],

/// Run time measurement registers.
pub rtmr: [u64; 24],

/// For future extension.
pub reserved: [u64; 14],
}

#[repr(C)]
#[derive(Pread)]
/// Output of TDCALL[TDG.MR.REPORT].
pub struct TdReport {
/// Mac protected header of size 256 bytes.
pub report_mac: ReportMac,

/// Additional attestable elements in the TCB are not reflected in the report_mac.
pub tee_tcb_info: [u8; 239],

/// Added for future extension.
pub reserved: [u8; 17],

/// Measurements and configuration data of size 512 bytes.
pub tdinfo: TdInfo,
}
Loading
Loading