Skip to content

Commit

Permalink
AA: Update CcaAttester to use TSM Report ABI
Browse files Browse the repository at this point in the history
Signed-off-by: Mathias Brossard <[email protected]>
  • Loading branch information
mathias-arm committed Jun 22, 2024
1 parent d7feaf8 commit f7dcee8
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 74 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ else ifeq ($(TEE_PLATFORM), amd)
else
RESOURCE_PROVIDER = sev,kbs
endif
else ifeq ($(TEE_PLATFORM), cca)
ATTESTER = cca-attester
endif
# TODO: Add support for CCA and CSV
# TODO: Add support for CSV

ifeq ($(ARCH), $(filter $(ARCH), s390x powerpc64le))
$(info s390x/powerpc64le only supports gnu)
Expand Down
3 changes: 2 additions & 1 deletion attestation-agent/attestation-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,14 @@ kbs = ["kbs_protocol/background_check", "token"]
# CoCoAS Attestation Token
coco_as = ["reqwest", "token"]

all-attesters = ["tdx-attester", "sgx-attester", "az-snp-vtpm-attester", "az-tdx-vtpm-attester", "snp-attester", "se-attester"]
all-attesters = ["tdx-attester", "sgx-attester", "az-snp-vtpm-attester", "az-tdx-vtpm-attester", "snp-attester", "se-attester", "cca-attester"]
tdx-attester = ["kbs_protocol?/tdx-attester", "attester/tdx-attester"]
sgx-attester = ["kbs_protocol?/sgx-attester", "attester/sgx-attester"]
az-snp-vtpm-attester = ["kbs_protocol?/az-snp-vtpm-attester", "attester/az-snp-vtpm-attester"]
az-tdx-vtpm-attester = ["kbs_protocol?/az-tdx-vtpm-attester", "attester/az-tdx-vtpm-attester"]
snp-attester = ["kbs_protocol?/snp-attester", "attester/snp-attester"]
se-attester = ["kbs_protocol?/se-attester", "attester/se-attester"]
cca-attester = ["kbs_protocol?/cca-attester", "attester/cca-attester"]

# Either `rust-crypto` or `openssl` should be enabled to work as underlying crypto module
rust-crypto = ["kbs_protocol?/rust-crypto"]
Expand Down
3 changes: 1 addition & 2 deletions attestation-agent/attester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ base64.workspace = true
clap = { workspace = true, features = ["derive"], optional = true }
kbs-types.workspace = true
log.workspace = true
nix = { version = "0.28", optional = true, features = ["ioctl", "fs"] }
occlum_dcap = { git = "https://github.com/occlum/occlum", tag = "v0.29.7", optional = true }
pv = { version = "0.10.0", package = "s390_pv", optional = true }
scroll = { version = "0.12.0", default-features = false, features = ["derive", "std"], optional = true }
Expand Down Expand Up @@ -67,7 +66,7 @@ az-snp-vtpm-attester = ["az-snp-vtpm"]
az-tdx-vtpm-attester = ["az-tdx-vtpm"]
snp-attester = ["sev"]
csv-attester = ["csv-rs", "codicon", "hyper", "hyper-tls", "tokio"]
cca-attester = ["nix"]
cca-attester = ["tsm-report"]
se-attester = ["pv"]

bin = ["tokio/rt", "tokio/macros", "clap"]
87 changes: 19 additions & 68 deletions attestation-agent/attester/src/cca/mod.rs
Original file line number Diff line number Diff line change
@@ -1,105 +1,56 @@
// Copyright (c) 2023 Arm Ltd.
// Copyright (c) 2023-2024 Arm Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//

use super::tsm_report::*;
use super::Attester;
use anyhow::*;
use base64::Engine;
use nix::fcntl::{open, OFlag};
use nix::sys::stat::Mode;
use nix::unistd::close;
use serde::{Deserialize, Serialize};
use std::path::Path;

const CCA_DEVICE_PATH: &str = "/dev/cca_attestation";
const CCA_CHALLENGE_SIZE: usize = 64;

// NOTE: The path might be different when the CCA feature is public available, will come back to update the actual path if needed.
pub fn detect_platform() -> bool {
Path::new(CCA_DEVICE_PATH).exists()
#[cfg(target_arch = "aarch64")]
return TsmReportPath::new(TsmReportProvider::Cca).is_ok();
#[cfg(not(target_arch = "aarch64"))]
return false;
}

#[derive(Debug, Default)]
pub struct CCAAttester {}
pub struct CcaAttester {}

#[derive(Serialize, Deserialize)]
struct CcaEvidence {
/// CCA token
token: Vec<u8>,
}

#[allow(non_camel_case_types)]
#[repr(C)]
pub struct cca_ioctl_request {
challenge: [u8; 64],
token: [u8; 4096],
token_length: u64,
}

nix::ioctl_readwrite!(cca_attestation_request, b'A', 1, cca_ioctl_request);

#[async_trait::async_trait]
impl Attester for CCAAttester {
impl Attester for CcaAttester {
async fn get_evidence(&self, mut challenge: Vec<u8>) -> Result<String> {
challenge.resize(64, 0);
let token = attestation(challenge)?;
if challenge.len() > CCA_CHALLENGE_SIZE {
bail!("CCA Attester: Challenge size must be {CCA_CHALLENGE_SIZE} or less.");
}

challenge.resize(CCA_CHALLENGE_SIZE, 0);
let tsm = TsmReportPath::new(TsmReportProvider::Tdx)?;
let token = tsm.attestation_report(TsmReportData::Cca(challenge))?;
let evidence = CcaEvidence { token };
let ev = serde_json::to_string(&evidence).context("Serialize CCA evidence failed")?;
let ev = serde_json::to_string(&evidence)
.context("Serialization of CCA evidence failed")?;
Ok(ev)
}
}

fn attestation(challenge: Vec<u8>) -> Result<Vec<u8>, Error> {
log::info!("cca_test::attestation started");

let challenge = challenge.as_slice().try_into()?;

match open(CCA_DEVICE_PATH, OFlag::empty(), Mode::empty()) {
Result::Ok(f) => {
log::info!("cca_test::attestation opening attestation succeeded");
let mut request = cca_ioctl_request {
challenge,
token: [0u8; 4096],
token_length: 0u64,
};

// this is unsafe code block since ioctl call `cca_attestation_request` has the unsafe signature.
match unsafe { cca_attestation_request(f, &mut request) } {
Result::Ok(c) => {
log::info!("cca_test::attestation ioctl call succeeded ({})", c);
log::info!(
"cca_test::attestation token is {} bytes long",
request.token_length
);
let base64 = base64::engine::general_purpose::STANDARD
.encode(&request.token[0..(request.token_length as usize)]);
log::info!("cca_test::attestation token = {:x?}", base64);
let token = request.token[0..(request.token_length as usize)].to_vec();
close(f)?;
Ok(token)
}
Err(e) => {
log::error!("cca_test::attestation ioctl failed! {}", e);
close(f)?;
bail!(e)
}
}
}
Err(err) => {
log::error!("cca_test::attestation opening attestation failed! {}", err);
bail!(err)
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[ignore]
#[tokio::test]
async fn test_cca_get_evidence() {
let attester = CCAAttester::default();
let attester = CcaAttester::default();
let report_data: Vec<u8> = vec![0; 48];
let evidence = attester.get_evidence(report_data).await;
assert!(evidence.is_ok());
Expand Down
2 changes: 1 addition & 1 deletion attestation-agent/attester/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl TryFrom<Tee> for BoxedAttester {
#[cfg(feature = "az-tdx-vtpm-attester")]
Tee::AzTdxVtpm => Box::<az_tdx_vtpm::AzTdxVtpmAttester>::default(),
#[cfg(feature = "cca-attester")]
Tee::Cca => Box::<cca::CCAAttester>::default(),
Tee::Cca => Box::<cca::CcaAttester>::default(),
#[cfg(feature = "snp-attester")]
Tee::Snp => Box::<snp::SnpAttester>::default(),
#[cfg(feature = "csv-attester")]
Expand Down
4 changes: 4 additions & 0 deletions attestation-agent/attester/src/tsm_report/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ pub enum TsmReportError {

#[derive(PartialEq, Debug, EnumString)]
pub enum TsmReportProvider {
#[strum(serialize = "arm_cca_guest\n")]
Cca,
#[strum(serialize = "tdx_guest\n")]
Tdx,
#[strum(serialize = "sev_guest\n")]
Sev,
}

pub enum TsmReportData {
Cca(Vec<u8>),
Tdx(Vec<u8>),
Sev(u8, Vec<u8>),
}
Expand Down Expand Up @@ -86,6 +89,7 @@ impl TsmReportPath {
let report_path = self.path.as_path();

let report_data = match provider_data {
TsmReportData::Cca(inblob) => inblob,
TsmReportData::Tdx(inblob) => inblob,
TsmReportData::Sev(privlevel, inblob) => {
// TODO: untested
Expand Down

0 comments on commit f7dcee8

Please sign in to comment.