From 0743c0d18c0e8249fa92daf629c9badfa6563a7a Mon Sep 17 00:00:00 2001 From: hairongchen Date: Mon, 25 Dec 2023 09:18:09 +0800 Subject: [PATCH 01/12] initial commit for Rust SDK framework for CC API VM SDK --- common/rust/cctrusted_base/Cargo.toml | 16 + common/rust/cctrusted_base/src/binary_blob.rs | 59 ++++ common/rust/cctrusted_base/src/cc_type.rs | 80 +++++ common/rust/cctrusted_base/src/eventlog.rs | 2 + common/rust/cctrusted_base/src/lib.rs | 10 + common/rust/cctrusted_base/src/tcg.rs | 41 +++ common/rust/cctrusted_base/src/tdx/common.rs | 42 +++ common/rust/cctrusted_base/src/tdx/mod.rs | 5 + common/rust/cctrusted_base/src/tdx/quote.rs | 280 ++++++++++++++++++ common/rust/cctrusted_base/src/tdx/report.rs | 194 ++++++++++++ common/rust/cctrusted_base/src/tdx/rtmr.rs | 26 ++ common/rust/cctrusted_base/src/tdx/tdx.rs | 121 ++++++++ common/rust/cctrusted_base/src/tee.rs | 46 +++ common/rust/cctrusted_base/src/tpm/mod.rs | 1 + common/rust/cctrusted_base/src/tpm/quote.rs | 10 + vmsdk/rust/cctrusted/Cargo.toml | 13 + vmsdk/rust/cctrusted/src/api.rs | 143 +++++++++ vmsdk/rust/cctrusted/src/api_data.rs | 65 ++++ vmsdk/rust/cctrusted/src/lib.rs | 2 + vmsdk/rust/sample/Cargo.toml | 14 + vmsdk/rust/sample/src/cc-sample.rs | 53 ++++ 21 files changed, 1223 insertions(+) create mode 100644 common/rust/cctrusted_base/Cargo.toml create mode 100644 common/rust/cctrusted_base/src/binary_blob.rs create mode 100644 common/rust/cctrusted_base/src/cc_type.rs create mode 100644 common/rust/cctrusted_base/src/eventlog.rs create mode 100644 common/rust/cctrusted_base/src/lib.rs create mode 100644 common/rust/cctrusted_base/src/tcg.rs create mode 100644 common/rust/cctrusted_base/src/tdx/common.rs create mode 100644 common/rust/cctrusted_base/src/tdx/mod.rs create mode 100644 common/rust/cctrusted_base/src/tdx/quote.rs create mode 100644 common/rust/cctrusted_base/src/tdx/report.rs create mode 100644 common/rust/cctrusted_base/src/tdx/rtmr.rs create mode 100644 common/rust/cctrusted_base/src/tdx/tdx.rs create mode 100644 common/rust/cctrusted_base/src/tee.rs create mode 100644 common/rust/cctrusted_base/src/tpm/mod.rs create mode 100644 common/rust/cctrusted_base/src/tpm/quote.rs create mode 100644 vmsdk/rust/cctrusted/Cargo.toml create mode 100644 vmsdk/rust/cctrusted/src/api.rs create mode 100644 vmsdk/rust/cctrusted/src/api_data.rs create mode 100644 vmsdk/rust/cctrusted/src/lib.rs create mode 100644 vmsdk/rust/sample/Cargo.toml create mode 100644 vmsdk/rust/sample/src/cc-sample.rs diff --git a/common/rust/cctrusted_base/Cargo.toml b/common/rust/cctrusted_base/Cargo.toml new file mode 100644 index 00000000..b783dfb3 --- /dev/null +++ b/common/rust/cctrusted_base/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cctrusted_base" +version = "0.1.0" +edition = "2021" + +[lib] +name = "cctrusted_base" +path = "src/lib.rs" + +[dependencies] +anyhow = "1.0" +base64 = "0.13.0" +log = "0.4.20" +sha2 = "0.10" +nix = "0.26.2" +lazy_static = "1.4.0" diff --git a/common/rust/cctrusted_base/src/binary_blob.rs b/common/rust/cctrusted_base/src/binary_blob.rs new file mode 100644 index 00000000..2d71a99b --- /dev/null +++ b/common/rust/cctrusted_base/src/binary_blob.rs @@ -0,0 +1,59 @@ +use log::info; + +/* dumnp raw cc report in following format: + 00000000 04 00 02 00 81 00 00 00 00 00 00 00 93 9A 72 33 ..............r3 + 00000010 F7 9C 4C A9 94 0A 0D B3 95 7F 06 07 D5 68 59 C7 ..L..........hY. + 00000020 35 FB B4 91 29 27 55 B2 E8 E8 23 B6 00 00 00 00 5...)'U...#..... +... +*/ + +pub fn dump_data(data: &Vec) { + let mut index: usize = 0; + let mut linestr = "".to_string(); + let mut printstr = "".to_string(); + + let printable = vec![ + ' ', '\t', '\n', '\r', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', + 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', + 'f', 'A', 'B', 'C', 'D', 'E', 'F', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', + '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', + '~', '"', '!', + ]; + + while usize::from(index) < data.len() { + if index % 16 == 0 { + if printstr.len() != 0 { + info!("{} {}", linestr, printstr); + printstr = "".to_string(); + } + linestr = format!("{:08X} ", ((index / 16) as u16) * 16); + } + + let v = data[index]; + linestr.push_str(format!("{:02X} ", v).as_str()); + match printable.iter().position(|&c| c == (v as char)) { + Some(_) => { + if v < 0x9 || v > 0xD { + printstr.push_str(std::str::from_utf8(&[v]).unwrap()); + } else { + printstr.push_str("."); + } + } + None => printstr.push_str("."), + } + + index += 1; + } + + if index % 16 != 0 { + let mut blank = "".to_string(); + for _ in 1..=(16 - index % 16) { + blank.push_str(" "); + } + info!("{}{} {}", linestr, blank, printstr); + } else if usize::from(index) == data.len() { + info!("{} {}", linestr, printstr); + } +} diff --git a/common/rust/cctrusted_base/src/cc_type.rs b/common/rust/cctrusted_base/src/cc_type.rs new file mode 100644 index 00000000..0ce6a9d2 --- /dev/null +++ b/common/rust/cctrusted_base/src/cc_type.rs @@ -0,0 +1,80 @@ +use anyhow::*; +use std::collections::HashMap; +use std::path::Path; +use std::result::Result; + +use crate::tee::TEE; +use crate::tcg::TcgAlgorithmRegistry; +use crate::tdx::tdx::Tdx; + +// supported TEE types +#[derive(Clone, Eq, Hash, PartialEq)] +pub enum TeeType { + PLAIN = -1, + TDX = 0, + SEV = 1, + CCA = 2, + TPM = 3, +} + +// TEE type to type name string mapping +lazy_static! { + pub static ref TEE_NAME_MAP: HashMap = { + let mut map: HashMap = HashMap::new(); + map.insert(TeeType::PLAIN, "PLAIN".to_string()); + map.insert(TeeType::TDX, "TDX".to_string()); + map.insert(TeeType::SEV, "SEV".to_string()); + map.insert(TeeType::CCA, "CCA".to_string()); + map.insert(TeeType::TPM, "TPM".to_string()); + map + }; +} + +// public known device node path +pub const TEE_TPM_PATH: &str = "/dev/tpm0"; +pub const TEE_TDX_1_0_PATH: &str = "/dev/tdx-guest"; +pub const TEE_TDX_1_5_PATH: &str = "/dev/tdx_guest"; +pub const TEE_SEV_PATH: &str = "/dev/sev-guest"; +pub const TEE_CCA_PATH: &str = ""; + +// holds the TEE type info +#[derive(Clone)] +pub struct CcType { + pub tee_type: TeeType, + pub tee_type_str: String, +} + +// used for return of Boxed trait object in build_tee() +pub trait BuildTee: TEE + TcgAlgorithmRegistry {} + +impl CcType { + // a function to detect the TEE type + pub fn new() -> CcType { + let mut tee_type = TeeType::PLAIN; + if Path::new(TEE_TPM_PATH).exists() { + tee_type = TeeType::TPM; + } else if Path::new(TEE_TDX_1_0_PATH).exists() || Path::new(TEE_TDX_1_5_PATH).exists() { + tee_type = TeeType::TDX; + } else if Path::new(TEE_SEV_PATH).exists() { + tee_type = TeeType::SEV; + } else { + // TODO add support for CCA and etc. + } + + CcType { + tee_type: tee_type.clone(), + tee_type_str: TEE_NAME_MAP.get(&tee_type).unwrap().to_owned(), + } + } + + pub fn build_tee() -> Result, anyhow::Error> { + // instance a tee according to detected TEE type + match CcType::new().tee_type { + TeeType::TDX => Ok(Box::new(Tdx::new())), + TeeType::SEV => todo!(), + TeeType::CCA => todo!(), + TeeType::TPM => todo!(), + TeeType::PLAIN => return Err(anyhow!("[build_tee] Error: not in any TEE!")), + } + } +} diff --git a/common/rust/cctrusted_base/src/eventlog.rs b/common/rust/cctrusted_base/src/eventlog.rs new file mode 100644 index 00000000..d63f1a7b --- /dev/null +++ b/common/rust/cctrusted_base/src/eventlog.rs @@ -0,0 +1,2 @@ +// struct for standard TCG eventlog +pub struct TcgEventLog {} diff --git a/common/rust/cctrusted_base/src/lib.rs b/common/rust/cctrusted_base/src/lib.rs new file mode 100644 index 00000000..c271e410 --- /dev/null +++ b/common/rust/cctrusted_base/src/lib.rs @@ -0,0 +1,10 @@ +#[macro_use] +extern crate lazy_static; + +pub mod binary_blob; +pub mod cc_type; +pub mod tee; +pub mod eventlog; +pub mod tcg; +pub mod tdx; +pub mod tpm; diff --git a/common/rust/cctrusted_base/src/tcg.rs b/common/rust/cctrusted_base/src/tcg.rs new file mode 100644 index 00000000..5a2c31b0 --- /dev/null +++ b/common/rust/cctrusted_base/src/tcg.rs @@ -0,0 +1,41 @@ +use std::collections::HashMap; + +pub const TPM_ALG_ERROR: u8 = 0x0; +pub const TPM_ALG_RSA: u8 = 0x1; +pub const TPM_ALG_TDES: u8 = 0x3; +pub const TPM_ALG_SHA256: u8 = 0xB; +pub const TPM_ALG_SHA384: u8 = 0xC; +pub const TPM_ALG_SHA512: u8 = 0xD; + +// hash algorithm ID to algorithm name string map +lazy_static! { + pub static ref ALGO_NAME_MAP: HashMap = { + let mut map: HashMap = HashMap::new(); + map.insert(TPM_ALG_ERROR, "TPM_ALG_RSA".to_string()); + map.insert(TPM_ALG_TDES, "TPM_ALG_TDES".to_string()); + map.insert(TPM_ALG_SHA256, "TPM_ALG_SHA256".to_string()); + map.insert(TPM_ALG_SHA384, "TPM_ALG_SHA384".to_string()); + map.insert(TPM_ALG_SHA512, "TPM_ALG_SHA512".to_string()); + map + }; +} + +// this trait retrieve tcg standard algorithm name in string +pub trait TcgAlgorithmRegistry { + fn get_algorithm_id(&self) -> u8; +} + +// digest format: (algo id, hash value) +#[allow(dead_code)] +pub struct TcgDigest { + algo_id: u8, + hash: Vec, +} + +// this trait retrieve IMR's max index of a TEE and hash value +pub trait TcgIMR { + fn max_index(&self) -> u8; + fn get_index(&self) -> u8; + fn get_hash(&self) -> Vec<&str>; + fn is_valid(&self) -> bool; +} diff --git a/common/rust/cctrusted_base/src/tdx/common.rs b/common/rust/cctrusted_base/src/tdx/common.rs new file mode 100644 index 00000000..ec959bc5 --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/common.rs @@ -0,0 +1,42 @@ +#![allow(non_camel_case_types)] +use crate::cc_type::*; +use std::collections::HashMap; + +// TDX version ID +#[derive(Clone, Eq, Hash, PartialEq)] +pub enum TdxVersion { + TDX_1_0, + TDX_1_5, +} + +// TDX version ID to version string map +lazy_static! { + pub static ref TDX_VERSION_MAP: HashMap = { + let mut map: HashMap = HashMap::new(); + map.insert(TdxVersion::TDX_1_0, "1.0".to_string()); + map.insert(TdxVersion::TDX_1_5, "1.5".to_string()); + map + }; +} + +// TDX version ID to device path string map +lazy_static! { + pub static ref TDX_DEVICE_NODE_MAP: HashMap = { + let mut map: HashMap = HashMap::new(); + map.insert(TdxVersion::TDX_1_0, TEE_TDX_1_0_PATH.to_string()); + map.insert(TdxVersion::TDX_1_5, TEE_TDX_1_5_PATH.to_string()); + map + }; +} + +// TDX ioctl operation code to be used for get TDX quote and TD Report +pub enum TdxOperation { + TDX_GET_TD_REPORT = 1, + TDX_1_0_GET_QUOTE = 2, + TDX_1_5_GET_QUOTE = 4, +} + +// quote and tdreport length +pub const REPORT_DATA_LEN: u32 = 64; +pub const TDX_REPORT_LEN: u32 = 1024; +pub const TDX_QUOTE_LEN: usize = 4 * 4096; diff --git a/common/rust/cctrusted_base/src/tdx/mod.rs b/common/rust/cctrusted_base/src/tdx/mod.rs new file mode 100644 index 00000000..c456e2bf --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/mod.rs @@ -0,0 +1,5 @@ +pub mod common; +pub mod quote; +pub mod report; +pub mod rtmr; +pub mod tdx; diff --git a/common/rust/cctrusted_base/src/tdx/quote.rs b/common/rust/cctrusted_base/src/tdx/quote.rs new file mode 100644 index 00000000..72e997c7 --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/quote.rs @@ -0,0 +1,280 @@ +#![allow(non_camel_case_types)] +use anyhow::*; +use nix::*; +use std::convert::TryInto; +use std::fs::File; +use std::mem; +use std::os::unix::io::AsRawFd; +use std::ptr; +use std::result::Result; +use std::result::Result::Ok; + +use super::common::*; +use super::tdx::*; + +#[repr(C)] +struct qgs_msg_header { + major_version: u16, // TDX major version + minor_version: u16, // TDX minor version + msg_type: u32, // GET_QUOTE_REQ or GET_QUOTE_RESP + size: u32, // size of the whole message, include this header, in byte + error_code: u32, // used in response only +} + +#[repr(C)] +struct qgs_msg_get_quote_req { + header: qgs_msg_header, // header.type = GET_QUOTE_REQ + report_size: u32, // cannot be 0 + id_list_size: u32, // length of id_list, in byte, can be 0 + report_id_list: [u8; TDX_REPORT_LEN as usize], // report followed by id list +} + +#[repr(C)] +struct tdx_quote_hdr { + version: u64, // Quote version, filled by TD + status: u64, // Status code of Quote request, filled by VMM + in_len: u32, // Length of TDREPORT, filled by TD + out_len: u32, // Length of Quote, filled by VMM + data_len_be_bytes: [u8; 4], // big-endian 4 bytes indicate the size of data following + data: [u8; TDX_QUOTE_LEN as usize], // Actual Quote data or TDREPORT on input +} + +#[repr(C)] +#[allow(private_in_public)] +struct tdx_quote_req { + buf: u64, // Pass user data that includes TDREPORT as input. Upon successful completion of IOCTL, output is copied back to the same buffer + len: u64, // Length of the Quote buffer +} + +#[repr(C)] +struct qgs_msg_get_quote_resp { + header: qgs_msg_header, // header.type = GET_QUOTE_RESP + selected_id_size: u32, // can be 0 in case only one id is sent in request + quote_size: u32, // length of quote_data, in byte + id_quote: [u8; TDX_QUOTE_LEN], // selected id followed by quote +} + +impl Tdx { + pub fn get_tdx_quote(&self, report_data: String) -> Result, anyhow::Error> { + //retrieve TDX report + let report_data_vec = match self.get_td_report(report_data) { + Err(e) => return Err(anyhow!("[get_tdx_quote] Fail to get TDX report: {:?}", e)), + Ok(report) => report, + }; + let report_data_array: [u8; TDX_REPORT_LEN as usize] = match report_data_vec.try_into() { + Ok(r) => r, + Err(e) => return Err(anyhow!("[get_tdx_quote] Wrong TDX report format: {:?}", e)), + }; + + //build QGS request message + let qgs_msg = self.generate_qgs_quote_msg(report_data_array); + + let device_node = match File::options() + .read(true) + .write(true) + .open(self.device_node.device_path.clone()) + { + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to open {}: {:?}", + self.device_node.device_path, + e + )) + } + Ok(fd) => fd, + }; + + //build quote generation request header + let mut quote_header = tdx_quote_hdr { + version: 1, + status: 0, + in_len: (mem::size_of_val(&qgs_msg) + 4) as u32, + out_len: 0, + data_len_be_bytes: (1048 as u32).to_be_bytes(), + data: [0; TDX_QUOTE_LEN as usize], + }; + + let qgs_msg_bytes = unsafe { + let ptr = &qgs_msg as *const qgs_msg_get_quote_req as *const u8; + std::slice::from_raw_parts(ptr, mem::size_of::()) + }; + quote_header.data[0..(16 + 8 + TDX_REPORT_LEN) as usize] + .copy_from_slice(&qgs_msg_bytes[0..((16 + 8 + TDX_REPORT_LEN) as usize)]); + + let request = tdx_quote_req { + buf: ptr::addr_of!(quote_header) as u64, + len: TDX_QUOTE_LEN as u64, + }; + + //build the operator code and apply the ioctl command + match self.version { + TdxVersion::TDX_1_0 => { + ioctl_read!( + get_quote_1_0_ioctl, + b'T', + TdxOperation::TDX_1_0_GET_QUOTE, + u64 + ); + match unsafe { + get_quote_1_0_ioctl(device_node.as_raw_fd(), ptr::addr_of!(request) as *mut u64) + } { + Err(e) => { + return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) + } + Ok(_r) => _r, + }; + } + TdxVersion::TDX_1_5 => { + ioctl_read!( + get_quote_1_5_ioctl, + b'T', + TdxOperation::TDX_1_5_GET_QUOTE, + tdx_quote_req + ); + match unsafe { + get_quote_1_5_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(request) as *mut tdx_quote_req, + ) + } { + Err(e) => { + return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) + } + Ok(_r) => _r, + }; + } + }; + + //inspect the response and retrive quote data + let out_len = quote_header.out_len; + let qgs_msg_resp_size = + unsafe { std::mem::transmute::<[u8; 4], u32>(quote_header.data_len_be_bytes) }.to_be(); + + let qgs_msg_resp = unsafe { + let raw_ptr = ptr::addr_of!(quote_header.data) as *mut qgs_msg_get_quote_resp; + raw_ptr.as_mut().unwrap() as &mut qgs_msg_get_quote_resp + }; + + if out_len - qgs_msg_resp_size != 4 { + return Err(anyhow!( + "[get_tdx_quote] Fail to get TDX quote: wrong TDX quote size!" + )); + } + + if qgs_msg_resp.header.major_version != 1 + || qgs_msg_resp.header.minor_version != 0 + || qgs_msg_resp.header.msg_type != 1 + || qgs_msg_resp.header.error_code != 0 + { + return Err(anyhow!( + "[get_tdx_quote] Fail to get TDX quote: QGS response error!" + )); + } + + Ok(qgs_msg_resp.id_quote[0..(qgs_msg_resp.quote_size as usize)].to_vec()) + } + + fn generate_qgs_quote_msg( + &self, + report: [u8; TDX_REPORT_LEN as usize], + ) -> qgs_msg_get_quote_req { + //build quote service message header to be used by QGS + let qgs_header = qgs_msg_header { + major_version: 1, + minor_version: 0, + msg_type: 0, + size: 16 + 8 + TDX_REPORT_LEN, // header + report_size and id_list_size + TDX_REPORT_LEN + error_code: 0, + }; + + //build quote service message body to be used by QGS + let mut qgs_request = qgs_msg_get_quote_req { + header: qgs_header, + report_size: TDX_REPORT_LEN, + id_list_size: 0, + report_id_list: [0; TDX_REPORT_LEN as usize], + }; + + qgs_request.report_id_list.copy_from_slice(&report[0..]); + + qgs_request + } +} + +// return of API parse_cc_report() +#[repr(C)] +// pub struct TdxQuote{ +// pub version: u16 // TD quote version +// pub tdreport: [u8; 584] // full TD report +// pub tee_type: u32 // Type of TEE for which the Quote has been generated +// pub tee_tcb_svn: [u8; 16] // Array of TEE TCB SVNs +// pub mrseam: [u8; 48] // Measurement of the SEAM module (SHA384 hash) +// pub mrseam_signer: [u8; 48] // Measurement of a 3rd party SEAM module’s signer (SHA384 hash) +// pub seam_attributes: [u8; 8] // ATTRIBUTES of SEAM +// pub td_attributes: [u8; 8] // ATTRIBUTES of TD +// pub xfam: [u8; 8] // XFAM of TD +// pub mrtd: [u8; 48] // Measurement of the initial contents of the TD (SHA384 hash) +// pub mrconfigid: [u8; 48] // Software defined ID for non-owner-defined configuration of the TD +// pub mrowner: [u8; 48] // Software defined ID for the guest TD’s owner +// pub mrownerconfig: [u8; 48] // Software defined ID for owner-defined configuration of the TD +// pub rtmrs: [u8; 192] // Array of 4 runtime extendable measurement registers (SHA384 hash) +// pub report_data: [u8; 64] // Additional Report Data +// pub signature: [u8; 64] // ECDSA signature, r component followed by s component, 2 x 32 bytes +// pub attestation_key: [u8; 64] // Public part of ECDSA Attestation Key generated by Quoting Enclave +// pub cert_data: Vec // Data required to certify Attestation Key used to sign the Quote +// } + +// pub struct TdxQuote { +// pub header: SGXQuoteHeader, +// pub tdreport: TDReport, +// pub signature: [u8; 64], // ECDSA signature, r component followed by s component, 2 x 32 bytes +// pub cert_data: Vec // Data required to certify Attestation Key used to sign the Quote +// } + +pub struct TdxQuote { + pub dummy_var1: u8, + pub dummy_var2: u8, +} + +#[repr(C)] +pub struct SGXQuoteHeader { + pub version: u16, // The version this quote structure. + pub attestation_key: u16, // sgx_attestation_algorithm_id_t. Describes the type of signature in the signature_data[] field. + pub tee_type: u32, // Type of Trusted Execution Environment for which the Quote has been generated. Supported values: 0 (SGX), 0x81(TDX) + pub reserved: u32, // Reserved field. + pub vendor_id: [u8; 16], // Unique identifier of QE Vendor. + pub user_data: [u8; 20], // Custom attestation key owner data. +} + +#[repr(C)] +pub struct TDReport { + pub tee_tcb_svn: [u8; 16], // Array of TEE TCB SVNs + pub mrseam: [u8; 48], // Measurement of the SEAM module (SHA384 hash) + pub mrseam_signer: [u8; 48], // Measurement of a 3rd party SEAM module’s signer (SHA384 hash) + pub seam_attributes: [u8; 8], // ATTRIBUTES of SEAM + pub td_attributes: [u8; 8], // ATTRIBUTES of TD + pub xfam: [u8; 8], // XFAM of TD + pub mrtd: [u8; 48], // Measurement of the initial contents of the TD (SHA384 hash) + pub mrconfigid: [u8; 48], // Software defined ID for non-owner-defined configuration of the TD + pub mrowner: [u8; 48], // Software defined ID for the guest TD’s owner + pub mrownerconfig: [u8; 48], // Software defined ID for owner-defined configuration of the TD + pub rtmrs: [u8; 192], // Array of 4 runtime extendable measurement registers (SHA384 hash) + pub report_data: [u8; 64], // Additional Report Data +} + +pub const QUOTE_HEADER_OFFSET: i32 = 0; // 48 bytes quote header, start from index 0 of quote string +pub const QUOTE_TDREPORT_OFFSET: i32 = 48; // 584 bytes tdreport, start from index 48 of quote string +pub const QUOTE_AUTH_DATA_SIZE_OFFSET: i32 = 632; // 4 bytes auth size, start from index 632 of quote string +pub const QUOTE_AUTH_DATA_CONTENT_OFFSET: i32 = 636; // authSize bytes in auth_data, start from index 636 of quote string +pub const QUOTE_AUTH_DATA_SIGNATURE_OFFSET: i32 = 700; // 64 bytes of signature in auth_data, start from index 700 of quote string +pub const QUOTE_AUTH_DATA_ATTESTATION_KEY_OFFSET: i32 = 764; // 64 bytes of attestation_key in auth_data, start from index 764 of quote string +pub const QUOTE_AUTH_DATA_CERT_DATA_OFFSET: i32 = 770; // (authSize-6-128) bytes of cert_data in auth_data, start from index 770 of quote string + +impl TdxQuote { + pub fn parse_tdx_quote(_quote: Vec) -> Result { + Ok(TdxQuote { + dummy_var1: 1, + dummy_var2: 2, + }) + } +} diff --git a/common/rust/cctrusted_base/src/tdx/report.rs b/common/rust/cctrusted_base/src/tdx/report.rs new file mode 100644 index 00000000..764b9d31 --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/report.rs @@ -0,0 +1,194 @@ +#![allow(non_camel_case_types)] +use anyhow::*; +use nix::*; +use sha2::{Digest, Sha512}; +use std::fs::File; +use std::os::unix::io::AsRawFd; +use std::ptr; +use std::result::Result; +use std::result::Result::Ok; + +use super::common::*; +use super::tdx::Tdx; + +#[repr(C)] +#[allow(private_in_public)] +struct tdx_1_0_report_req { + subtype: u8, // Subtype of TDREPORT: fixed as 0 by TDX Module specification + reportdata: u64, // User-defined REPORTDATA to be included into TDREPORT + rpd_len: u32, // Length of the REPORTDATA: fixed as 64 bytes by the TDX Module specification + tdreport: u64, // TDREPORT output from TDCALL[TDG.MR.REPORT] + tdr_len: u32, // Length of the TDREPORT: fixed as 1024 bytes by the TDX Module specification +} + +#[repr(C)] +#[allow(private_in_public)] +struct tdx_1_5_report_req { + reportdata: [u8; REPORT_DATA_LEN as usize], // User buffer with REPORTDATA to be included into TDREPORT + tdreport: [u8; TDX_REPORT_LEN as usize], // User buffer to store TDREPORT output from TDCALL[TDG.MR.REPORT] +} + +impl Tdx { + pub fn generate_tdx_report_data( + &self, + nonce: String, + data: Option, + ) -> Result { + let nonce_decoded = match base64::decode(nonce) { + Ok(v) => v, + Err(e) => { + return Err(anyhow!( + "[generate_tdx_report_data] nonce is not base64 encoded: {:?}", + e + )) + } + }; + let mut hasher = Sha512::new(); + hasher.update(nonce_decoded); + let _ret = match data { + Some(_encoded_data) => { + if _encoded_data.is_empty() { + hasher.update("") + } else { + let decoded_data = match base64::decode(_encoded_data) { + Ok(v) => v, + Err(e) => { + return Err(anyhow!( + "[generate_tdx_report_data] user data is not base64 encoded: {:?}", + e + )) + } + }; + hasher.update(decoded_data) + } + } + None => hasher.update(""), + }; + let hash_array: [u8; 64] = hasher + .finalize() + .as_slice() + .try_into() + .expect("[generate_tdx_report_data] Wrong length of report data"); + Ok(base64::encode(hash_array)) + } + + pub fn get_td_report(&self, report_data: String) -> Result, anyhow::Error> { + let device_node = match File::options() + .read(true) + .write(true) + .open(self.device_node.device_path.clone()) + { + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to open {}: {:?}", + self.device_node.device_path, + e + )) + } + Ok(fd) => fd, + }; + + match self.version { + TdxVersion::TDX_1_0 => match self.get_tdx_1_0_report(device_node, report_data) { + Err(e) => return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)), + Ok(report) => Ok(report), + }, + TdxVersion::TDX_1_5 => match self.get_tdx_1_5_report(device_node, report_data) { + Err(e) => return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)), + Ok(report) => Ok(report), + }, + } + } + + fn get_tdx_1_0_report( + &self, + device_node: File, + report_data: String, + ) -> Result, anyhow::Error> { + let report_data_bytes = match base64::decode(report_data) { + Ok(v) => v, + Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), + }; + + //prepare get TDX report request data + let mut report_data_array: [u8; REPORT_DATA_LEN as usize] = [0; REPORT_DATA_LEN as usize]; + report_data_array.copy_from_slice(&report_data_bytes[0..]); + let td_report: [u8; TDX_REPORT_LEN as usize] = [0; TDX_REPORT_LEN as usize]; + + //build the request + let request = tdx_1_0_report_req { + subtype: 0 as u8, + reportdata: ptr::addr_of!(report_data_array) as u64, + rpd_len: REPORT_DATA_LEN, + tdreport: ptr::addr_of!(td_report) as u64, + tdr_len: TDX_REPORT_LEN, + }; + + //build the operator code + ioctl_readwrite!( + get_report_1_0_ioctl, + b'T', + TdxOperation::TDX_GET_TD_REPORT, + u64 + ); + + //apply the ioctl command + match unsafe { + get_report_1_0_ioctl(device_node.as_raw_fd(), ptr::addr_of!(request) as *mut u64) + } { + Err(e) => { + return Err(anyhow!( + "[get_tdx_1_0_report] Fail to get TDX report: {:?}", + e + )) + } + Ok(_) => (), + }; + + Ok(td_report.to_vec()) + } + + fn get_tdx_1_5_report( + &self, + device_node: File, + report_data: String, + ) -> Result, anyhow::Error> { + let report_data_bytes = match base64::decode(report_data) { + Ok(v) => v, + Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), + }; + + //prepare get TDX report request data + let mut request = tdx_1_5_report_req { + reportdata: [0; REPORT_DATA_LEN as usize], + tdreport: [0; TDX_REPORT_LEN as usize], + }; + request.reportdata.copy_from_slice(&report_data_bytes[0..]); + + //build the operator code + ioctl_readwrite!( + get_report_1_5_ioctl, + b'T', + TdxOperation::TDX_GET_TD_REPORT, + tdx_1_5_report_req + ); + + //apply the ioctl command + match unsafe { + get_report_1_5_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(request) as *mut tdx_1_5_report_req, + ) + } { + Err(e) => { + return Err(anyhow!( + "[get_tdx_1_5_report] Fail to get TDX report: {:?}", + e + )) + } + Ok(_) => (), + }; + + Ok(request.tdreport.to_vec()) + } +} diff --git a/common/rust/cctrusted_base/src/tdx/rtmr.rs b/common/rust/cctrusted_base/src/tdx/rtmr.rs new file mode 100644 index 00000000..72357921 --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/rtmr.rs @@ -0,0 +1,26 @@ +use crate::tcg::*; +use std::collections::HashMap; + +#[allow(dead_code)] +pub struct TdxRTMR { + index: u8, + digests: HashMap, +} + +impl TcgIMR for TdxRTMR { + fn max_index(&self) -> u8 { + return 3; + } + + fn get_index(&self) -> u8 { + todo!() + } + + fn get_hash(&self) -> Vec<&str> { + todo!() + } + + fn is_valid(&self) -> bool { + todo!() + } +} diff --git a/common/rust/cctrusted_base/src/tdx/tdx.rs b/common/rust/cctrusted_base/src/tdx/tdx.rs new file mode 100644 index 00000000..2e026c6e --- /dev/null +++ b/common/rust/cctrusted_base/src/tdx/tdx.rs @@ -0,0 +1,121 @@ +use anyhow::*; +use log::info; +use std::result::Result::Ok; + +use crate::cc_type::*; +use crate::tee::*; +use crate::tcg::{TcgAlgorithmRegistry, TcgDigest}; +use crate::tdx::common::*; +use crate::tdx::rtmr::TdxRTMR; +use std::path::Path; + +/* + Tdx is an abstraction of TDX running environment, it contains: + cc_type: should always be CcType built with TeeType::TDX + version: TdxVersion::TDX_1_0 or TdxVersion::TDX_1_5 + device_node: /dev/tdx-guest or /dev/tdx_guest + algo_id: should be TPM_ALG_SHA384 + cc_report_raw: the raw tdx quote in byte array + td_report_raw: the raw td report in byte array + rtrms: array of TdxRTMR struct +*/ +pub struct Tdx { + pub cc_type: CcType, + pub version: TdxVersion, + pub device_node: DeviceNode, + pub algo_id: u8, + pub cc_report_raw: Vec, + pub td_report_raw: Vec, + pub rtrms: Vec, +} + +// implement the structure method and associated function +impl Tdx { + // associated function: to build a Tdx sturcture instance + pub fn new() -> Tdx { + let cc_type = CcType { + tee_type: TeeType::TDX, + tee_type_str: TEE_NAME_MAP.get(&TeeType::TDX).unwrap().to_owned(), + }; + + let version = Self::get_tdx_version(); + let device_node = DeviceNode { + device_path: TDX_DEVICE_NODE_MAP.get(&version).unwrap().to_owned(), + }; + let algo_id = crate::tcg::TPM_ALG_SHA384; + + Tdx { + cc_type, + version, + device_node, + algo_id, + cc_report_raw: Vec::new(), + td_report_raw: Vec::new(), + rtrms: Vec::new(), + } + } + + // associated function to detect the TDX version + fn get_tdx_version() -> TdxVersion { + if Path::new(TEE_TDX_1_0_PATH).exists() { + TdxVersion::TDX_1_0 + } else if Path::new(TEE_TDX_1_5_PATH).exists() { + TdxVersion::TDX_1_5 + } else { + TdxVersion::TDX_1_0 + } + } +} + +// Tdx implements the interfaces defined in TEE trait +impl TEE for Tdx { + // retrieve TDX quote + fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error> { + let report_data = match self.generate_tdx_report_data(nonce, Some(data)) { + Ok(r) => r, + Err(e) => { + return Err(anyhow!( + "[get_cc_report] error generating TDX report data: {:?}", + e + )) + } + }; + + match self.get_tdx_quote(report_data) { + Ok(q) => Ok(q), + Err(e) => return Err(anyhow!("[get_cc_report] error getting TDX quote: {:?}", e)), + } + } + + // retrieve TDX RTMR + fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest { + todo!() + } + + // retrieve TDX CCEL and IMA eventlog + fn process_cc_eventlog(&self) -> () { + todo!() + } + + fn get_cc_type(&self) -> CcType { + return self.cc_type.clone(); + } + + fn dump(&self) { + info!("======================================"); + info!("TEE type = {}", self.cc_type.tee_type_str); + info!( + "TEE version = {}", + TDX_VERSION_MAP.get(&self.version).unwrap().to_owned() + ); + info!("======================================"); + } +} + +impl TcgAlgorithmRegistry for Tdx { + fn get_algorithm_id(&self) -> u8 { + self.algo_id + } +} + +impl BuildTee for Tdx {} diff --git a/common/rust/cctrusted_base/src/tee.rs b/common/rust/cctrusted_base/src/tee.rs new file mode 100644 index 00000000..a570ca2d --- /dev/null +++ b/common/rust/cctrusted_base/src/tee.rs @@ -0,0 +1,46 @@ +use crate::cc_type::CcType; +use crate::tcg::TcgDigest; + +// holds the device node info +pub struct DeviceNode { + pub device_path: String, +} + +pub struct CcEventlogs { + //TODO +} + +// the interfaces a TEE should implement +pub trait TEE { + /*** + retrive TEE signed report + + Args: + nonce (String): against replay attacks + data (String): user data + + Returns: + the cc report byte array or error information + */ + fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error>; + + /*** + retrive TEE measurement registers, e.g.: RTMRs, vTPM PCRs, etc. + + Args: + index (u8): the index of measurement register, + algo_id (u8): the alrogithms ID + + Returns: + TcgDigest struct + */ + fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest; + + //TODO! + fn process_cc_eventlog(&self); + + fn get_cc_type(&self) -> CcType; + + //Dump confidential TEE information + fn dump(&self); +} diff --git a/common/rust/cctrusted_base/src/tpm/mod.rs b/common/rust/cctrusted_base/src/tpm/mod.rs new file mode 100644 index 00000000..9e1a6d43 --- /dev/null +++ b/common/rust/cctrusted_base/src/tpm/mod.rs @@ -0,0 +1 @@ +pub mod quote; diff --git a/common/rust/cctrusted_base/src/tpm/quote.rs b/common/rust/cctrusted_base/src/tpm/quote.rs new file mode 100644 index 00000000..5da67b2f --- /dev/null +++ b/common/rust/cctrusted_base/src/tpm/quote.rs @@ -0,0 +1,10 @@ +// return of API parse_cc_report() +pub struct TpmQuote { + // TODO +} + +impl TpmQuote { + pub fn parse_tpm_quote(_quote: Vec) -> Result { + todo!() + } +} diff --git a/vmsdk/rust/cctrusted/Cargo.toml b/vmsdk/rust/cctrusted/Cargo.toml new file mode 100644 index 00000000..3e393a60 --- /dev/null +++ b/vmsdk/rust/cctrusted/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "cctrusted" +version = "0.1.0" +edition = "2021" + +[lib] +name = "cctrusted" +path = "src/lib.rs" + +[dependencies] +cctrusted_base = { path = "../../../common/rust/cctrusted_base" } +anyhow = "1.0" +log = "0.4.20" diff --git a/vmsdk/rust/cctrusted/src/api.rs b/vmsdk/rust/cctrusted/src/api.rs new file mode 100644 index 00000000..f7eae01b --- /dev/null +++ b/vmsdk/rust/cctrusted/src/api.rs @@ -0,0 +1,143 @@ +use anyhow::*; +use std::mem; +use std::result::Result; +use std::result::Result::Ok; + +use cctrusted_base::binary_blob::dump_data; +use cctrusted_base::cc_type::CcType; +use cctrusted_base::eventlog::TcgEventLog; +use cctrusted_base::tcg::{TcgDigest, ALGO_NAME_MAP}; +use cctrusted_base::tdx::quote::TdxQuote; +use cctrusted_base::tpm::quote::TpmQuote; + +use crate::api_data::*; + +/*** + Get the cc report for given nonce and data. + + The cc report is signing of attestation data (IMR values or hashes of IMR + values), made by a trusted foundation (TPM) using a key trusted by the + verifier. + + Different trusted foundation may use different cc report format. + + Args: + nonce (String): against replay attacks + data (String): user data + extraArgs: for TPM, it will be given list of IMR/PCRs + + Returns: + The cc report byte array or error information +*/ +pub fn get_cc_report( + nonce: String, + data: String, + _extra_args: ExtraArgs, +) -> Result { + match CcType::build_tee() { + Ok(mut tee) => { + // call tee trait defined methods + tee.dump(); + Ok(CcReport { + cc_report: match tee.process_cc_report(nonce, data) { + Ok(r) => r, + Err(e) => { + return Err(anyhow!("[get_cc_report] error get cc report: {:?}", e)); + } + }, + cc_type: tee.get_cc_type().tee_type as i8, + }) + } + Err(e) => return Err(anyhow!("[get_cc_report] error create tee: {:?}", e)), + } +} + +pub fn dump_cc_report(report: &Vec) { + dump_data(report) +} + +/*** + Get measurement register according to given selected index and algorithms + + Each trusted foundation in CC environment provides the multiple measurement + registers, the count is update to ``get_measurement_count()``. And for each + measurement register, it may provides multiple digest for different algorithms. + + Args: + index (u8): the index of measurement register, + algo_id (u8): the alrogithms ID + + Returns: + TcgDigest struct +*/ +pub fn get_cc_measurement(_index: u8, _algo_id: u8) -> TcgDigest { + todo!() +} + +/*** + Get eventlog for given index and count. + + TCG log in Eventlog. Verify to spoof events in the TCG log, hence defeating + remotely-attested measured-boot. + + To measure the full CC runtime environment, the eventlog may include addtional + OS type and cloud native type event beyond the measured-boot. + + Returns: + TcgEventLog struct +*/ +pub fn get_cc_eventlog(_start: u16, _count: u16) -> TcgEventLog { + todo!() +} + +/*** + Get the default Digest algorithms supported by trusted foundation. + + Different trusted foundation may support different algorithms, for example + the Intel TDX use SHA384, TPM uses SHA256. + + Beyond the default digest algorithm, some trusted foundation like TPM + may support multiple algorithms. + + Returns: + The Algorithm struct + +*/ +pub fn get_default_algorithm() -> Result { + match CcType::build_tee() { + Ok(tee) => { + // call tee trait defined methods + let algo_id = tee.get_algorithm_id(); + Ok(Algorithm { + algo_id: algo_id, + algo_id_str: ALGO_NAME_MAP.get(&algo_id).unwrap().to_owned(), + }) + } + Err(e) => { + return Err(anyhow!( + "[get_default_algorithm] error get algorithm: {:?}", + e + )) + } + } +} + +// this function parses cc report to the TDX quote struct +impl ParseCcReport for CcReport { + fn parse_cc_report(report: Vec) -> Result { + match TdxQuote::parse_tdx_quote(report) { + Ok(tdx_quote) => unsafe { + let report: &CcParsedTdxReport = mem::transmute(&tdx_quote); + Ok(report.clone()) + }, + Err(e) => return Err(anyhow!("[parse_cc_report] error parse tdx quote: {:?}", e)), + } + } +} + +// this function parses cc report to the TPM quote struct +impl ParseCcReport for CcReport { + fn parse_cc_report(_report: Vec) -> Result { + todo!() + } +} diff --git a/vmsdk/rust/cctrusted/src/api_data.rs b/vmsdk/rust/cctrusted/src/api_data.rs new file mode 100644 index 00000000..ffce19b7 --- /dev/null +++ b/vmsdk/rust/cctrusted/src/api_data.rs @@ -0,0 +1,65 @@ +/*** + ************************************ + * API get_cc_report() related data * + ************************************ + */ + +// input of API get_cc_report() +// this struct is used in vTPM and other TEE scenarios +// e.g.: vTPM may need report based on selective PCRs +pub struct ExtraArgs {} + +pub const TYPE_PLAIN: i8 = -1; +pub const TYPE_TDX: i8 = 0; +pub const TYPE_SEV: i8 = 1; +pub const TYPE_CCA: i8 = 2; +pub const TYPE_TPM: i8 = 3; + +// return of API get_cc_report() +pub struct CcReport { + pub cc_report: Vec, + pub cc_type: i8, +} + +/*** + ************************************** + * API parse_cc_report() related data * + ************************************** + */ +// return of API parse_cc_report() in TDX case +#[derive(Clone)] +pub struct CcParsedTdxReport { + pub dummy_var1: u8, + pub dummy_var2: u8, +} + +// return of API parse_cc_report() in TPM case +pub struct CcParsedTpmReport {} + +/*** + trait to be implemented for cc report parsing. + + the cooresponding implementation of parse_cc_report will be called according to + intented return format and the return of the trait function depends on + the type of cc report, e.g.: TdxQuote, TpmQuote and etc. + + TDX quote parsing Example: + if following is provided: + let tdx_quote: TdxQuote = parse_cc_report(cc_report_str); + then this implementation in api.rs will be called: + fn parse_cc_report(report: Vec) -> Result; +*/ +pub trait ParseCcReport { + fn parse_cc_report(_report: Vec) -> Result; +} + +/*** + ******************************************** + * API get_default_algorithm() related data * + ******************************************** + */ +// return structure for get_default_algorithm +pub struct Algorithm { + pub algo_id: u8, + pub algo_id_str: String, +} diff --git a/vmsdk/rust/cctrusted/src/lib.rs b/vmsdk/rust/cctrusted/src/lib.rs new file mode 100644 index 00000000..08b00c1a --- /dev/null +++ b/vmsdk/rust/cctrusted/src/lib.rs @@ -0,0 +1,2 @@ +pub mod api; +pub mod api_data; diff --git a/vmsdk/rust/sample/Cargo.toml b/vmsdk/rust/sample/Cargo.toml new file mode 100644 index 00000000..bf76d984 --- /dev/null +++ b/vmsdk/rust/sample/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "cctrusted-sample" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "cc-sample" +path = "src/cc-sample.rs" + +[dependencies] +cctrusted = { path = "../cctrusted" } +anyhow = "1.0" +log = "0.4.20" +env_logger = "0.10.0" diff --git a/vmsdk/rust/sample/src/cc-sample.rs b/vmsdk/rust/sample/src/cc-sample.rs new file mode 100644 index 00000000..a5fe8944 --- /dev/null +++ b/vmsdk/rust/sample/src/cc-sample.rs @@ -0,0 +1,53 @@ +use cctrusted::api::*; +use cctrusted::api_data::*; +use log::*; + +fn main() { + // set log level + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let nonce = "MTIzNDU2Nzg=".to_string(); + let data = "YWJjZGVmZw==".to_string(); + + // retrieve cc report with API "get_cc_report" + info!("call cc trusted API [get_cc_report] to retrieve cc report!"); + let report = match get_cc_report(nonce, data, ExtraArgs {}) { + Ok(q) => q, + Err(e) => { + error!("error getting TDX report: {:?}", e); + return; + } + }; + + // dump the cc report with API "dump_cc_report" + info!("call cc trusted API [dump_cc_report] to dump cc report!"); + dump_cc_report(&report.cc_report); + + // parse the cc report with API "parse_cc_report" + if report.cc_type == TYPE_TDX { + let tdx_quote: CcParsedTdxReport = match CcReport::parse_cc_report(report.cc_report) { + Ok(q) => q, + Err(e) => { + error!("error parse tdx quote: {:?}", e); + return; + } + }; + info!( + "dummy_var1 = {}, dummy_var2 = {}", + tdx_quote.dummy_var1, tdx_quote.dummy_var2 + ); + } + + // get TEE default algorithm with API "get_default_algorithm" + info!("call cc trusted API [get_default_algorithm] to get TEE supported algorithm!"); + match get_default_algorithm() { + Ok(algorithm) => { + info!("supported algorithm: {}", algorithm.algo_id_str); + (); + } + Err(e) => { + error!("error get algorithm: {:?}", e); + return; + } + }; +} From df34b3d66530e04b535f7a0d81a8b57170533d47 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Mon, 25 Dec 2023 12:15:24 +0800 Subject: [PATCH 02/12] update according to comments: move type TPM to 0 --- common/rust/cctrusted_base/src/cc_type.rs | 8 ++++---- vmsdk/rust/cctrusted/src/api_data.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/rust/cctrusted_base/src/cc_type.rs b/common/rust/cctrusted_base/src/cc_type.rs index 0ce6a9d2..3034c705 100644 --- a/common/rust/cctrusted_base/src/cc_type.rs +++ b/common/rust/cctrusted_base/src/cc_type.rs @@ -11,10 +11,10 @@ use crate::tdx::tdx::Tdx; #[derive(Clone, Eq, Hash, PartialEq)] pub enum TeeType { PLAIN = -1, - TDX = 0, - SEV = 1, - CCA = 2, - TPM = 3, + TPM = 0, + TDX = 1, + SEV = 2, + CCA = 3, } // TEE type to type name string mapping diff --git a/vmsdk/rust/cctrusted/src/api_data.rs b/vmsdk/rust/cctrusted/src/api_data.rs index ffce19b7..c5d08047 100644 --- a/vmsdk/rust/cctrusted/src/api_data.rs +++ b/vmsdk/rust/cctrusted/src/api_data.rs @@ -10,10 +10,10 @@ pub struct ExtraArgs {} pub const TYPE_PLAIN: i8 = -1; -pub const TYPE_TDX: i8 = 0; -pub const TYPE_SEV: i8 = 1; -pub const TYPE_CCA: i8 = 2; -pub const TYPE_TPM: i8 = 3; +pub const TYPE_TPM: i8 = 0; +pub const TYPE_TDX: i8 = 1; +pub const TYPE_SEV: i8 = 2; +pub const TYPE_CCA: i8 = 3; // return of API get_cc_report() pub struct CcReport { From 1716b8c6efe395705a7c1eb8759036b10d3a1ece Mon Sep 17 00:00:00 2001 From: hairongchen Date: Mon, 25 Dec 2023 12:22:21 +0800 Subject: [PATCH 03/12] clear code and format --- common/rust/cctrusted_base/src/tdx/quote.rs | 64 --------------------- 1 file changed, 64 deletions(-) diff --git a/common/rust/cctrusted_base/src/tdx/quote.rs b/common/rust/cctrusted_base/src/tdx/quote.rs index 72e997c7..a257d051 100644 --- a/common/rust/cctrusted_base/src/tdx/quote.rs +++ b/common/rust/cctrusted_base/src/tdx/quote.rs @@ -201,75 +201,11 @@ impl Tdx { } } -// return of API parse_cc_report() -#[repr(C)] -// pub struct TdxQuote{ -// pub version: u16 // TD quote version -// pub tdreport: [u8; 584] // full TD report -// pub tee_type: u32 // Type of TEE for which the Quote has been generated -// pub tee_tcb_svn: [u8; 16] // Array of TEE TCB SVNs -// pub mrseam: [u8; 48] // Measurement of the SEAM module (SHA384 hash) -// pub mrseam_signer: [u8; 48] // Measurement of a 3rd party SEAM module’s signer (SHA384 hash) -// pub seam_attributes: [u8; 8] // ATTRIBUTES of SEAM -// pub td_attributes: [u8; 8] // ATTRIBUTES of TD -// pub xfam: [u8; 8] // XFAM of TD -// pub mrtd: [u8; 48] // Measurement of the initial contents of the TD (SHA384 hash) -// pub mrconfigid: [u8; 48] // Software defined ID for non-owner-defined configuration of the TD -// pub mrowner: [u8; 48] // Software defined ID for the guest TD’s owner -// pub mrownerconfig: [u8; 48] // Software defined ID for owner-defined configuration of the TD -// pub rtmrs: [u8; 192] // Array of 4 runtime extendable measurement registers (SHA384 hash) -// pub report_data: [u8; 64] // Additional Report Data -// pub signature: [u8; 64] // ECDSA signature, r component followed by s component, 2 x 32 bytes -// pub attestation_key: [u8; 64] // Public part of ECDSA Attestation Key generated by Quoting Enclave -// pub cert_data: Vec // Data required to certify Attestation Key used to sign the Quote -// } - -// pub struct TdxQuote { -// pub header: SGXQuoteHeader, -// pub tdreport: TDReport, -// pub signature: [u8; 64], // ECDSA signature, r component followed by s component, 2 x 32 bytes -// pub cert_data: Vec // Data required to certify Attestation Key used to sign the Quote -// } - pub struct TdxQuote { pub dummy_var1: u8, pub dummy_var2: u8, } -#[repr(C)] -pub struct SGXQuoteHeader { - pub version: u16, // The version this quote structure. - pub attestation_key: u16, // sgx_attestation_algorithm_id_t. Describes the type of signature in the signature_data[] field. - pub tee_type: u32, // Type of Trusted Execution Environment for which the Quote has been generated. Supported values: 0 (SGX), 0x81(TDX) - pub reserved: u32, // Reserved field. - pub vendor_id: [u8; 16], // Unique identifier of QE Vendor. - pub user_data: [u8; 20], // Custom attestation key owner data. -} - -#[repr(C)] -pub struct TDReport { - pub tee_tcb_svn: [u8; 16], // Array of TEE TCB SVNs - pub mrseam: [u8; 48], // Measurement of the SEAM module (SHA384 hash) - pub mrseam_signer: [u8; 48], // Measurement of a 3rd party SEAM module’s signer (SHA384 hash) - pub seam_attributes: [u8; 8], // ATTRIBUTES of SEAM - pub td_attributes: [u8; 8], // ATTRIBUTES of TD - pub xfam: [u8; 8], // XFAM of TD - pub mrtd: [u8; 48], // Measurement of the initial contents of the TD (SHA384 hash) - pub mrconfigid: [u8; 48], // Software defined ID for non-owner-defined configuration of the TD - pub mrowner: [u8; 48], // Software defined ID for the guest TD’s owner - pub mrownerconfig: [u8; 48], // Software defined ID for owner-defined configuration of the TD - pub rtmrs: [u8; 192], // Array of 4 runtime extendable measurement registers (SHA384 hash) - pub report_data: [u8; 64], // Additional Report Data -} - -pub const QUOTE_HEADER_OFFSET: i32 = 0; // 48 bytes quote header, start from index 0 of quote string -pub const QUOTE_TDREPORT_OFFSET: i32 = 48; // 584 bytes tdreport, start from index 48 of quote string -pub const QUOTE_AUTH_DATA_SIZE_OFFSET: i32 = 632; // 4 bytes auth size, start from index 632 of quote string -pub const QUOTE_AUTH_DATA_CONTENT_OFFSET: i32 = 636; // authSize bytes in auth_data, start from index 636 of quote string -pub const QUOTE_AUTH_DATA_SIGNATURE_OFFSET: i32 = 700; // 64 bytes of signature in auth_data, start from index 700 of quote string -pub const QUOTE_AUTH_DATA_ATTESTATION_KEY_OFFSET: i32 = 764; // 64 bytes of attestation_key in auth_data, start from index 764 of quote string -pub const QUOTE_AUTH_DATA_CERT_DATA_OFFSET: i32 = 770; // (authSize-6-128) bytes of cert_data in auth_data, start from index 770 of quote string - impl TdxQuote { pub fn parse_tdx_quote(_quote: Vec) -> Result { Ok(TdxQuote { From 254da5257c8b6cdede2fd8d704dbbaf319a635e1 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 28 Dec 2023 09:52:01 +0800 Subject: [PATCH 04/12] This commit fix follows: 1. update crate common/cctrusetd_base does not depend on std crates 2. change crate name from cctrusted to cctrusted_vm for VM SDK to in-sync with Python latest update 3. define trait CCTrustedApi in crate common/cctrusetd_base to define general cc trusted APIs 4. change api to sdk concept in cctrusted_vm crate 5. move CVM related functions to cctrusted_vm crate 6. update TCG algo list to reflact review comments by Jiewen --- common/rust/cctrusted_base/Cargo.toml | 3 +- common/rust/cctrusted_base/src/api.rs | 128 +++++++ common/rust/cctrusted_base/src/api_data.rs | 40 ++ common/rust/cctrusted_base/src/binary_blob.rs | 2 +- common/rust/cctrusted_base/src/cc_type.rs | 44 +-- common/rust/cctrusted_base/src/lib.rs | 3 +- common/rust/cctrusted_base/src/tcg.rs | 13 +- common/rust/cctrusted_base/src/tdx/common.rs | 11 +- common/rust/cctrusted_base/src/tdx/mod.rs | 1 - common/rust/cctrusted_base/src/tdx/quote.rs | 197 ++-------- common/rust/cctrusted_base/src/tdx/report.rs | 163 ++------ common/rust/cctrusted_base/src/tdx/rtmr.rs | 2 +- common/rust/cctrusted_base/src/tdx/tdx.rs | 121 ------ common/rust/cctrusted_base/src/tee.rs | 46 --- common/rust/cctrusted_base/src/tpm/quote.rs | 4 +- vmsdk/rust/cctrusted/src/api.rs | 143 ------- vmsdk/rust/cctrusted/src/api_data.rs | 65 ---- vmsdk/rust/cctrusted/src/lib.rs | 2 - .../{cctrusted => cctrusted_vm}/Cargo.toml | 6 +- vmsdk/rust/cctrusted_vm/src/cvm.rs | 100 +++++ vmsdk/rust/cctrusted_vm/src/lib.rs | 3 + vmsdk/rust/cctrusted_vm/src/sdk.rs | 74 ++++ vmsdk/rust/cctrusted_vm/src/tdvm.rs | 352 ++++++++++++++++++ vmsdk/rust/sample/Cargo.toml | 5 +- vmsdk/rust/sample/src/cc-sample.rs | 21 +- 25 files changed, 795 insertions(+), 754 deletions(-) create mode 100644 common/rust/cctrusted_base/src/api.rs create mode 100644 common/rust/cctrusted_base/src/api_data.rs delete mode 100644 common/rust/cctrusted_base/src/tdx/tdx.rs delete mode 100644 common/rust/cctrusted_base/src/tee.rs delete mode 100644 vmsdk/rust/cctrusted/src/api.rs delete mode 100644 vmsdk/rust/cctrusted/src/api_data.rs delete mode 100644 vmsdk/rust/cctrusted/src/lib.rs rename vmsdk/rust/{cctrusted => cctrusted_vm}/Cargo.toml (70%) create mode 100644 vmsdk/rust/cctrusted_vm/src/cvm.rs create mode 100644 vmsdk/rust/cctrusted_vm/src/lib.rs create mode 100644 vmsdk/rust/cctrusted_vm/src/sdk.rs create mode 100644 vmsdk/rust/cctrusted_vm/src/tdvm.rs diff --git a/common/rust/cctrusted_base/Cargo.toml b/common/rust/cctrusted_base/Cargo.toml index b783dfb3..91e97766 100644 --- a/common/rust/cctrusted_base/Cargo.toml +++ b/common/rust/cctrusted_base/Cargo.toml @@ -12,5 +12,6 @@ anyhow = "1.0" base64 = "0.13.0" log = "0.4.20" sha2 = "0.10" -nix = "0.26.2" lazy_static = "1.4.0" +hashbrown = "0.14" + diff --git a/common/rust/cctrusted_base/src/api.rs b/common/rust/cctrusted_base/src/api.rs new file mode 100644 index 00000000..e97b3c4d --- /dev/null +++ b/common/rust/cctrusted_base/src/api.rs @@ -0,0 +1,128 @@ +use crate::api_data::Algorithm; +use crate::api_data::*; +use crate::eventlog::TcgEventLog; +use crate::tcg::TcgDigest; +use crate::tdx::quote::TdxQuote; +use crate::tpm::quote::TpmQuote; +use anyhow::*; +use core::mem; +use core::result::Result; +use core::result::Result::Ok; + +pub trait CCTrustedApi { + /*** + Get the cc report for given nonce and data. + + The cc report is signing of attestation data (IMR values or hashes of IMR + values), made by a trusted foundation (TPM) using a key trusted by the + verifier. + + Different trusted foundation may use different cc report format. + + Args: + nonce (String): against replay attacks + data (String): user data + extraArgs: for TPM, it will be given list of IMR/PCRs + + Returns: + The cc report byte array or error information + */ + fn get_cc_report( + nonce: String, + data: String, + _extra_args: ExtraArgs, + ) -> Result; + + /*** + Dump the given cc report in hex and char format + + Args: + report (Vec): cc report to be printed + + Returns: + None + */ + fn dump_cc_report(report: &Vec); + + /*** + Get measurement register according to given selected index and algorithms + + Each trusted foundation in CC environment provides the multiple measurement + registers, the count is update to ``get_measurement_count()``. And for each + measurement register, it may provides multiple digest for different algorithms. + + Args: + index (u8): the index of measurement register, + algo_id (u8): the alrogithms ID + + Returns: + TcgDigest struct + */ + fn get_cc_measurement(_index: u8, _algo_id: u8) -> TcgDigest; + + /*** + Get eventlog for given index and count. + + TCG log in Eventlog. Verify to spoof events in the TCG log, hence defeating + remotely-attested measured-boot. + + To measure the full CC runtime environment, the eventlog may include addtional + OS type and cloud native type event beyond the measured-boot. + + Returns: + TcgEventLog struct + */ + fn get_cc_eventlog(_start: u16, _count: u16) -> TcgEventLog; + + /*** + Get the default Digest algorithms supported by trusted foundation. + + Different trusted foundation may support different algorithms, for example + the Intel TDX use SHA384, TPM uses SHA256. + + Beyond the default digest algorithm, some trusted foundation like TPM + may support multiple algorithms. + + Returns: + The Algorithm struct + + */ + fn get_default_algorithm() -> Result; +} + +/*** + trait to be implemented for cc report parsing. + + the cooresponding implementation of parse_cc_report will be called according to + intented return format and the return of the trait function depends on + the type of cc report, e.g.: TdxQuote, TpmQuote and etc. + + TDX quote parsing Example: + if following is provided: + let tdx_quote: TdxQuote = parse_cc_report(cc_report_str); + then this implementation in api.rs will be called: + fn parse_cc_report(report: Vec) -> Result; +*/ +pub trait ParseCcReport { + fn parse_cc_report(_report: Vec) -> Result; +} + +// API function parses raw cc report to TdxQuote struct +impl ParseCcReport for CcReport { + fn parse_cc_report(report: Vec) -> Result { + match TdxQuote::parse_tdx_quote(report) { + Ok(tdx_quote) => unsafe { + let report: &TdxQuote = mem::transmute(&tdx_quote); + Ok(report.clone()) + }, + Err(e) => return Err(anyhow!("[parse_cc_report] error parse tdx quote: {:?}", e)), + } + } +} + +// API function parses raw cc report to TpmQuote struct +impl ParseCcReport for CcReport { + fn parse_cc_report(_report: Vec) -> Result { + todo!() + } +} diff --git a/common/rust/cctrusted_base/src/api_data.rs b/common/rust/cctrusted_base/src/api_data.rs new file mode 100644 index 00000000..89f2c06d --- /dev/null +++ b/common/rust/cctrusted_base/src/api_data.rs @@ -0,0 +1,40 @@ +use crate::cc_type::TeeType; + +/*** + ************************************ + * API get_cc_report() related data * + ************************************ + */ +// input of API get_cc_report() +// this struct is used in vTPM and other CVM scenarios +// e.g.: vTPM may need report based on selective PCRs +pub struct ExtraArgs {} + +// return of API get_cc_report() +pub struct CcReport { + pub cc_report: Vec, + pub cc_type: TeeType, +} + +/*** + ************************************** + * API parse_cc_report() related data * + ************************************** +*/ +/*** + the return data structure is defined in cctrusted_base + e.g.: + - cctrusted_base::tdx::quote::TdxQuote; + - cctrusted_base::tpm::quote::TpmQuote; +*/ + +/*** + ******************************************** + * API get_default_algorithm() related data * + ******************************************** + */ +// return structure for get_default_algorithm +pub struct Algorithm { + pub algo_id: u8, + pub algo_id_str: String, +} diff --git a/common/rust/cctrusted_base/src/binary_blob.rs b/common/rust/cctrusted_base/src/binary_blob.rs index 2d71a99b..88dadbb3 100644 --- a/common/rust/cctrusted_base/src/binary_blob.rs +++ b/common/rust/cctrusted_base/src/binary_blob.rs @@ -36,7 +36,7 @@ pub fn dump_data(data: &Vec) { match printable.iter().position(|&c| c == (v as char)) { Some(_) => { if v < 0x9 || v > 0xD { - printstr.push_str(std::str::from_utf8(&[v]).unwrap()); + printstr.push_str(core::str::from_utf8(&[v]).unwrap()); } else { printstr.push_str("."); } diff --git a/common/rust/cctrusted_base/src/cc_type.rs b/common/rust/cctrusted_base/src/cc_type.rs index 3034c705..5282e4c6 100644 --- a/common/rust/cctrusted_base/src/cc_type.rs +++ b/common/rust/cctrusted_base/src/cc_type.rs @@ -1,11 +1,4 @@ -use anyhow::*; -use std::collections::HashMap; -use std::path::Path; -use std::result::Result; - -use crate::tee::TEE; -use crate::tcg::TcgAlgorithmRegistry; -use crate::tdx::tdx::Tdx; +use hashbrown::HashMap; // supported TEE types #[derive(Clone, Eq, Hash, PartialEq)] @@ -43,38 +36,3 @@ pub struct CcType { pub tee_type: TeeType, pub tee_type_str: String, } - -// used for return of Boxed trait object in build_tee() -pub trait BuildTee: TEE + TcgAlgorithmRegistry {} - -impl CcType { - // a function to detect the TEE type - pub fn new() -> CcType { - let mut tee_type = TeeType::PLAIN; - if Path::new(TEE_TPM_PATH).exists() { - tee_type = TeeType::TPM; - } else if Path::new(TEE_TDX_1_0_PATH).exists() || Path::new(TEE_TDX_1_5_PATH).exists() { - tee_type = TeeType::TDX; - } else if Path::new(TEE_SEV_PATH).exists() { - tee_type = TeeType::SEV; - } else { - // TODO add support for CCA and etc. - } - - CcType { - tee_type: tee_type.clone(), - tee_type_str: TEE_NAME_MAP.get(&tee_type).unwrap().to_owned(), - } - } - - pub fn build_tee() -> Result, anyhow::Error> { - // instance a tee according to detected TEE type - match CcType::new().tee_type { - TeeType::TDX => Ok(Box::new(Tdx::new())), - TeeType::SEV => todo!(), - TeeType::CCA => todo!(), - TeeType::TPM => todo!(), - TeeType::PLAIN => return Err(anyhow!("[build_tee] Error: not in any TEE!")), - } - } -} diff --git a/common/rust/cctrusted_base/src/lib.rs b/common/rust/cctrusted_base/src/lib.rs index c271e410..c4255190 100644 --- a/common/rust/cctrusted_base/src/lib.rs +++ b/common/rust/cctrusted_base/src/lib.rs @@ -1,9 +1,10 @@ #[macro_use] extern crate lazy_static; +pub mod api; +pub mod api_data; pub mod binary_blob; pub mod cc_type; -pub mod tee; pub mod eventlog; pub mod tcg; pub mod tdx; diff --git a/common/rust/cctrusted_base/src/tcg.rs b/common/rust/cctrusted_base/src/tcg.rs index 5a2c31b0..047aa765 100644 --- a/common/rust/cctrusted_base/src/tcg.rs +++ b/common/rust/cctrusted_base/src/tcg.rs @@ -1,21 +1,24 @@ -use std::collections::HashMap; +use hashbrown::HashMap; pub const TPM_ALG_ERROR: u8 = 0x0; pub const TPM_ALG_RSA: u8 = 0x1; -pub const TPM_ALG_TDES: u8 = 0x3; +pub const TPM_ALG_SHA1: u8 = 0x4; pub const TPM_ALG_SHA256: u8 = 0xB; pub const TPM_ALG_SHA384: u8 = 0xC; pub const TPM_ALG_SHA512: u8 = 0xD; +pub const TPM_ALG_ECDSA: u8 = 0x18; // hash algorithm ID to algorithm name string map lazy_static! { pub static ref ALGO_NAME_MAP: HashMap = { let mut map: HashMap = HashMap::new(); - map.insert(TPM_ALG_ERROR, "TPM_ALG_RSA".to_string()); - map.insert(TPM_ALG_TDES, "TPM_ALG_TDES".to_string()); + map.insert(TPM_ALG_ERROR, "TPM_ALG_ERROR".to_string()); + map.insert(TPM_ALG_RSA, "TPM_ALG_RSA".to_string()); + map.insert(TPM_ALG_SHA1, "TPM_ALG_SHA1".to_string()); map.insert(TPM_ALG_SHA256, "TPM_ALG_SHA256".to_string()); map.insert(TPM_ALG_SHA384, "TPM_ALG_SHA384".to_string()); map.insert(TPM_ALG_SHA512, "TPM_ALG_SHA512".to_string()); + map.insert(TPM_ALG_ECDSA, "TPM_ALG_ECDSA".to_string()); map }; } @@ -32,7 +35,7 @@ pub struct TcgDigest { hash: Vec, } -// this trait retrieve IMR's max index of a TEE and hash value +// this trait retrieve IMR's max index of a CVM and hash value pub trait TcgIMR { fn max_index(&self) -> u8; fn get_index(&self) -> u8; diff --git a/common/rust/cctrusted_base/src/tdx/common.rs b/common/rust/cctrusted_base/src/tdx/common.rs index ec959bc5..d48f9a43 100644 --- a/common/rust/cctrusted_base/src/tdx/common.rs +++ b/common/rust/cctrusted_base/src/tdx/common.rs @@ -1,6 +1,8 @@ #![allow(non_camel_case_types)] use crate::cc_type::*; -use std::collections::HashMap; +use hashbrown::HashMap; + +pub struct Tdx {} // TDX version ID #[derive(Clone, Eq, Hash, PartialEq)] @@ -29,13 +31,6 @@ lazy_static! { }; } -// TDX ioctl operation code to be used for get TDX quote and TD Report -pub enum TdxOperation { - TDX_GET_TD_REPORT = 1, - TDX_1_0_GET_QUOTE = 2, - TDX_1_5_GET_QUOTE = 4, -} - // quote and tdreport length pub const REPORT_DATA_LEN: u32 = 64; pub const TDX_REPORT_LEN: u32 = 1024; diff --git a/common/rust/cctrusted_base/src/tdx/mod.rs b/common/rust/cctrusted_base/src/tdx/mod.rs index c456e2bf..8adee353 100644 --- a/common/rust/cctrusted_base/src/tdx/mod.rs +++ b/common/rust/cctrusted_base/src/tdx/mod.rs @@ -2,4 +2,3 @@ pub mod common; pub mod quote; pub mod report; pub mod rtmr; -pub mod tdx; diff --git a/common/rust/cctrusted_base/src/tdx/quote.rs b/common/rust/cctrusted_base/src/tdx/quote.rs index a257d051..9f81fc3d 100644 --- a/common/rust/cctrusted_base/src/tdx/quote.rs +++ b/common/rust/cctrusted_base/src/tdx/quote.rs @@ -1,183 +1,61 @@ #![allow(non_camel_case_types)] -use anyhow::*; -use nix::*; -use std::convert::TryInto; -use std::fs::File; -use std::mem; -use std::os::unix::io::AsRawFd; -use std::ptr; -use std::result::Result; -use std::result::Result::Ok; +use core::result::Result; +use core::result::Result::Ok; -use super::common::*; -use super::tdx::*; +use crate::tdx::common::*; #[repr(C)] -struct qgs_msg_header { - major_version: u16, // TDX major version - minor_version: u16, // TDX minor version - msg_type: u32, // GET_QUOTE_REQ or GET_QUOTE_RESP - size: u32, // size of the whole message, include this header, in byte - error_code: u32, // used in response only +pub struct qgs_msg_header { + pub major_version: u16, // TDX major version + pub minor_version: u16, // TDX minor version + pub msg_type: u32, // GET_QUOTE_REQ or GET_QUOTE_RESP + pub size: u32, // size of the whole message, include this header, in byte + pub error_code: u32, // used in response only } #[repr(C)] -struct qgs_msg_get_quote_req { - header: qgs_msg_header, // header.type = GET_QUOTE_REQ - report_size: u32, // cannot be 0 - id_list_size: u32, // length of id_list, in byte, can be 0 - report_id_list: [u8; TDX_REPORT_LEN as usize], // report followed by id list +pub struct qgs_msg_get_quote_req { + pub header: qgs_msg_header, // header.type = GET_QUOTE_REQ + pub report_size: u32, // cannot be 0 + pub id_list_size: u32, // length of id_list, in byte, can be 0 + pub report_id_list: [u8; TDX_REPORT_LEN as usize], // report followed by id list } #[repr(C)] -struct tdx_quote_hdr { - version: u64, // Quote version, filled by TD - status: u64, // Status code of Quote request, filled by VMM - in_len: u32, // Length of TDREPORT, filled by TD - out_len: u32, // Length of Quote, filled by VMM - data_len_be_bytes: [u8; 4], // big-endian 4 bytes indicate the size of data following - data: [u8; TDX_QUOTE_LEN as usize], // Actual Quote data or TDREPORT on input +pub struct tdx_quote_hdr { + pub version: u64, // Quote version, filled by TD + pub status: u64, // Status code of Quote request, filled by VMM + pub in_len: u32, // Length of TDREPORT, filled by TD + pub out_len: u32, // Length of Quote, filled by VMM + pub data_len_be_bytes: [u8; 4], // big-endian 4 bytes indicate the size of data following + pub data: [u8; TDX_QUOTE_LEN as usize], // Actual Quote data or TDREPORT on input } #[repr(C)] -#[allow(private_in_public)] -struct tdx_quote_req { - buf: u64, // Pass user data that includes TDREPORT as input. Upon successful completion of IOCTL, output is copied back to the same buffer - len: u64, // Length of the Quote buffer +pub struct tdx_quote_req { + pub buf: u64, // Pass user data that includes TDREPORT as input. Upon successful completion of IOCTL, output is copied back to the same buffer + pub len: u64, // Length of the Quote buffer } #[repr(C)] -struct qgs_msg_get_quote_resp { - header: qgs_msg_header, // header.type = GET_QUOTE_RESP - selected_id_size: u32, // can be 0 in case only one id is sent in request - quote_size: u32, // length of quote_data, in byte - id_quote: [u8; TDX_QUOTE_LEN], // selected id followed by quote +pub struct qgs_msg_get_quote_resp { + pub header: qgs_msg_header, // header.type = GET_QUOTE_RESP + pub selected_id_size: u32, // can be 0 in case only one id is sent in request + pub quote_size: u32, // length of quote_data, in byte + pub id_quote: [u8; TDX_QUOTE_LEN], // selected id followed by quote } impl Tdx { - pub fn get_tdx_quote(&self, report_data: String) -> Result, anyhow::Error> { - //retrieve TDX report - let report_data_vec = match self.get_td_report(report_data) { - Err(e) => return Err(anyhow!("[get_tdx_quote] Fail to get TDX report: {:?}", e)), - Ok(report) => report, - }; - let report_data_array: [u8; TDX_REPORT_LEN as usize] = match report_data_vec.try_into() { - Ok(r) => r, - Err(e) => return Err(anyhow!("[get_tdx_quote] Wrong TDX report format: {:?}", e)), - }; - - //build QGS request message - let qgs_msg = self.generate_qgs_quote_msg(report_data_array); - - let device_node = match File::options() - .read(true) - .write(true) - .open(self.device_node.device_path.clone()) - { - Err(e) => { - return Err(anyhow!( - "[get_td_report] Fail to open {}: {:?}", - self.device_node.device_path, - e - )) - } - Ok(fd) => fd, - }; + /*** + generate qgs message for TDX quote generation - //build quote generation request header - let mut quote_header = tdx_quote_hdr { - version: 1, - status: 0, - in_len: (mem::size_of_val(&qgs_msg) + 4) as u32, - out_len: 0, - data_len_be_bytes: (1048 as u32).to_be_bytes(), - data: [0; TDX_QUOTE_LEN as usize], - }; - - let qgs_msg_bytes = unsafe { - let ptr = &qgs_msg as *const qgs_msg_get_quote_req as *const u8; - std::slice::from_raw_parts(ptr, mem::size_of::()) - }; - quote_header.data[0..(16 + 8 + TDX_REPORT_LEN) as usize] - .copy_from_slice(&qgs_msg_bytes[0..((16 + 8 + TDX_REPORT_LEN) as usize)]); - - let request = tdx_quote_req { - buf: ptr::addr_of!(quote_header) as u64, - len: TDX_QUOTE_LEN as u64, - }; - - //build the operator code and apply the ioctl command - match self.version { - TdxVersion::TDX_1_0 => { - ioctl_read!( - get_quote_1_0_ioctl, - b'T', - TdxOperation::TDX_1_0_GET_QUOTE, - u64 - ); - match unsafe { - get_quote_1_0_ioctl(device_node.as_raw_fd(), ptr::addr_of!(request) as *mut u64) - } { - Err(e) => { - return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) - } - Ok(_r) => _r, - }; - } - TdxVersion::TDX_1_5 => { - ioctl_read!( - get_quote_1_5_ioctl, - b'T', - TdxOperation::TDX_1_5_GET_QUOTE, - tdx_quote_req - ); - match unsafe { - get_quote_1_5_ioctl( - device_node.as_raw_fd(), - ptr::addr_of!(request) as *mut tdx_quote_req, - ) - } { - Err(e) => { - return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) - } - Ok(_r) => _r, - }; - } - }; - - //inspect the response and retrive quote data - let out_len = quote_header.out_len; - let qgs_msg_resp_size = - unsafe { std::mem::transmute::<[u8; 4], u32>(quote_header.data_len_be_bytes) }.to_be(); - - let qgs_msg_resp = unsafe { - let raw_ptr = ptr::addr_of!(quote_header.data) as *mut qgs_msg_get_quote_resp; - raw_ptr.as_mut().unwrap() as &mut qgs_msg_get_quote_resp - }; - - if out_len - qgs_msg_resp_size != 4 { - return Err(anyhow!( - "[get_tdx_quote] Fail to get TDX quote: wrong TDX quote size!" - )); - } - - if qgs_msg_resp.header.major_version != 1 - || qgs_msg_resp.header.minor_version != 0 - || qgs_msg_resp.header.msg_type != 1 - || qgs_msg_resp.header.error_code != 0 - { - return Err(anyhow!( - "[get_tdx_quote] Fail to get TDX quote: QGS response error!" - )); - } - - Ok(qgs_msg_resp.id_quote[0..(qgs_msg_resp.quote_size as usize)].to_vec()) - } + Args: + report (Vec): tdreport - fn generate_qgs_quote_msg( - &self, - report: [u8; TDX_REPORT_LEN as usize], - ) -> qgs_msg_get_quote_req { + Returns: + qgs_msg_get_quote_req struct instance + */ + pub fn generate_qgs_quote_msg(report: [u8; TDX_REPORT_LEN as usize]) -> qgs_msg_get_quote_req { //build quote service message header to be used by QGS let qgs_header = qgs_msg_header { major_version: 1, @@ -201,6 +79,7 @@ impl Tdx { } } +#[derive(Clone)] pub struct TdxQuote { pub dummy_var1: u8, pub dummy_var2: u8, diff --git a/common/rust/cctrusted_base/src/tdx/report.rs b/common/rust/cctrusted_base/src/tdx/report.rs index 764b9d31..902c24f6 100644 --- a/common/rust/cctrusted_base/src/tdx/report.rs +++ b/common/rust/cctrusted_base/src/tdx/report.rs @@ -1,36 +1,37 @@ #![allow(non_camel_case_types)] +use crate::tdx::common::*; use anyhow::*; -use nix::*; +use core::result::Result; +use core::result::Result::Ok; use sha2::{Digest, Sha512}; -use std::fs::File; -use std::os::unix::io::AsRawFd; -use std::ptr; -use std::result::Result; -use std::result::Result::Ok; - -use super::common::*; -use super::tdx::Tdx; #[repr(C)] -#[allow(private_in_public)] -struct tdx_1_0_report_req { - subtype: u8, // Subtype of TDREPORT: fixed as 0 by TDX Module specification - reportdata: u64, // User-defined REPORTDATA to be included into TDREPORT - rpd_len: u32, // Length of the REPORTDATA: fixed as 64 bytes by the TDX Module specification - tdreport: u64, // TDREPORT output from TDCALL[TDG.MR.REPORT] - tdr_len: u32, // Length of the TDREPORT: fixed as 1024 bytes by the TDX Module specification +pub struct tdx_1_0_report_req { + pub subtype: u8, // Subtype of TDREPORT: fixed as 0 by TDX Module specification + pub reportdata: u64, // User-defined REPORTDATA to be included into TDREPORT + pub rpd_len: u32, // Length of the REPORTDATA: fixed as 64 bytes by the TDX Module specification + pub tdreport: u64, // TDREPORT output from TDCALL[TDG.MR.REPORT] + pub tdr_len: u32, // Length of the TDREPORT: fixed as 1024 bytes by the TDX Module specification } #[repr(C)] -#[allow(private_in_public)] -struct tdx_1_5_report_req { - reportdata: [u8; REPORT_DATA_LEN as usize], // User buffer with REPORTDATA to be included into TDREPORT - tdreport: [u8; TDX_REPORT_LEN as usize], // User buffer to store TDREPORT output from TDCALL[TDG.MR.REPORT] +pub struct tdx_1_5_report_req { + pub reportdata: [u8; REPORT_DATA_LEN as usize], // User buffer with REPORTDATA to be included into TDREPORT + pub tdreport: [u8; TDX_REPORT_LEN as usize], // User buffer to store TDREPORT output from TDCALL[TDG.MR.REPORT] } impl Tdx { + /*** + generate tdx report data with nonce and data + + Args: + nonce (String): against replay attacks + data (String): user data + + Returns: + The tdreport byte array + */ pub fn generate_tdx_report_data( - &self, nonce: String, data: Option, ) -> Result { @@ -71,124 +72,4 @@ impl Tdx { .expect("[generate_tdx_report_data] Wrong length of report data"); Ok(base64::encode(hash_array)) } - - pub fn get_td_report(&self, report_data: String) -> Result, anyhow::Error> { - let device_node = match File::options() - .read(true) - .write(true) - .open(self.device_node.device_path.clone()) - { - Err(e) => { - return Err(anyhow!( - "[get_td_report] Fail to open {}: {:?}", - self.device_node.device_path, - e - )) - } - Ok(fd) => fd, - }; - - match self.version { - TdxVersion::TDX_1_0 => match self.get_tdx_1_0_report(device_node, report_data) { - Err(e) => return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)), - Ok(report) => Ok(report), - }, - TdxVersion::TDX_1_5 => match self.get_tdx_1_5_report(device_node, report_data) { - Err(e) => return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)), - Ok(report) => Ok(report), - }, - } - } - - fn get_tdx_1_0_report( - &self, - device_node: File, - report_data: String, - ) -> Result, anyhow::Error> { - let report_data_bytes = match base64::decode(report_data) { - Ok(v) => v, - Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), - }; - - //prepare get TDX report request data - let mut report_data_array: [u8; REPORT_DATA_LEN as usize] = [0; REPORT_DATA_LEN as usize]; - report_data_array.copy_from_slice(&report_data_bytes[0..]); - let td_report: [u8; TDX_REPORT_LEN as usize] = [0; TDX_REPORT_LEN as usize]; - - //build the request - let request = tdx_1_0_report_req { - subtype: 0 as u8, - reportdata: ptr::addr_of!(report_data_array) as u64, - rpd_len: REPORT_DATA_LEN, - tdreport: ptr::addr_of!(td_report) as u64, - tdr_len: TDX_REPORT_LEN, - }; - - //build the operator code - ioctl_readwrite!( - get_report_1_0_ioctl, - b'T', - TdxOperation::TDX_GET_TD_REPORT, - u64 - ); - - //apply the ioctl command - match unsafe { - get_report_1_0_ioctl(device_node.as_raw_fd(), ptr::addr_of!(request) as *mut u64) - } { - Err(e) => { - return Err(anyhow!( - "[get_tdx_1_0_report] Fail to get TDX report: {:?}", - e - )) - } - Ok(_) => (), - }; - - Ok(td_report.to_vec()) - } - - fn get_tdx_1_5_report( - &self, - device_node: File, - report_data: String, - ) -> Result, anyhow::Error> { - let report_data_bytes = match base64::decode(report_data) { - Ok(v) => v, - Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), - }; - - //prepare get TDX report request data - let mut request = tdx_1_5_report_req { - reportdata: [0; REPORT_DATA_LEN as usize], - tdreport: [0; TDX_REPORT_LEN as usize], - }; - request.reportdata.copy_from_slice(&report_data_bytes[0..]); - - //build the operator code - ioctl_readwrite!( - get_report_1_5_ioctl, - b'T', - TdxOperation::TDX_GET_TD_REPORT, - tdx_1_5_report_req - ); - - //apply the ioctl command - match unsafe { - get_report_1_5_ioctl( - device_node.as_raw_fd(), - ptr::addr_of!(request) as *mut tdx_1_5_report_req, - ) - } { - Err(e) => { - return Err(anyhow!( - "[get_tdx_1_5_report] Fail to get TDX report: {:?}", - e - )) - } - Ok(_) => (), - }; - - Ok(request.tdreport.to_vec()) - } } diff --git a/common/rust/cctrusted_base/src/tdx/rtmr.rs b/common/rust/cctrusted_base/src/tdx/rtmr.rs index 72357921..e0cc9c6c 100644 --- a/common/rust/cctrusted_base/src/tdx/rtmr.rs +++ b/common/rust/cctrusted_base/src/tdx/rtmr.rs @@ -1,5 +1,5 @@ use crate::tcg::*; -use std::collections::HashMap; +use hashbrown::HashMap; #[allow(dead_code)] pub struct TdxRTMR { diff --git a/common/rust/cctrusted_base/src/tdx/tdx.rs b/common/rust/cctrusted_base/src/tdx/tdx.rs deleted file mode 100644 index 2e026c6e..00000000 --- a/common/rust/cctrusted_base/src/tdx/tdx.rs +++ /dev/null @@ -1,121 +0,0 @@ -use anyhow::*; -use log::info; -use std::result::Result::Ok; - -use crate::cc_type::*; -use crate::tee::*; -use crate::tcg::{TcgAlgorithmRegistry, TcgDigest}; -use crate::tdx::common::*; -use crate::tdx::rtmr::TdxRTMR; -use std::path::Path; - -/* - Tdx is an abstraction of TDX running environment, it contains: - cc_type: should always be CcType built with TeeType::TDX - version: TdxVersion::TDX_1_0 or TdxVersion::TDX_1_5 - device_node: /dev/tdx-guest or /dev/tdx_guest - algo_id: should be TPM_ALG_SHA384 - cc_report_raw: the raw tdx quote in byte array - td_report_raw: the raw td report in byte array - rtrms: array of TdxRTMR struct -*/ -pub struct Tdx { - pub cc_type: CcType, - pub version: TdxVersion, - pub device_node: DeviceNode, - pub algo_id: u8, - pub cc_report_raw: Vec, - pub td_report_raw: Vec, - pub rtrms: Vec, -} - -// implement the structure method and associated function -impl Tdx { - // associated function: to build a Tdx sturcture instance - pub fn new() -> Tdx { - let cc_type = CcType { - tee_type: TeeType::TDX, - tee_type_str: TEE_NAME_MAP.get(&TeeType::TDX).unwrap().to_owned(), - }; - - let version = Self::get_tdx_version(); - let device_node = DeviceNode { - device_path: TDX_DEVICE_NODE_MAP.get(&version).unwrap().to_owned(), - }; - let algo_id = crate::tcg::TPM_ALG_SHA384; - - Tdx { - cc_type, - version, - device_node, - algo_id, - cc_report_raw: Vec::new(), - td_report_raw: Vec::new(), - rtrms: Vec::new(), - } - } - - // associated function to detect the TDX version - fn get_tdx_version() -> TdxVersion { - if Path::new(TEE_TDX_1_0_PATH).exists() { - TdxVersion::TDX_1_0 - } else if Path::new(TEE_TDX_1_5_PATH).exists() { - TdxVersion::TDX_1_5 - } else { - TdxVersion::TDX_1_0 - } - } -} - -// Tdx implements the interfaces defined in TEE trait -impl TEE for Tdx { - // retrieve TDX quote - fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error> { - let report_data = match self.generate_tdx_report_data(nonce, Some(data)) { - Ok(r) => r, - Err(e) => { - return Err(anyhow!( - "[get_cc_report] error generating TDX report data: {:?}", - e - )) - } - }; - - match self.get_tdx_quote(report_data) { - Ok(q) => Ok(q), - Err(e) => return Err(anyhow!("[get_cc_report] error getting TDX quote: {:?}", e)), - } - } - - // retrieve TDX RTMR - fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest { - todo!() - } - - // retrieve TDX CCEL and IMA eventlog - fn process_cc_eventlog(&self) -> () { - todo!() - } - - fn get_cc_type(&self) -> CcType { - return self.cc_type.clone(); - } - - fn dump(&self) { - info!("======================================"); - info!("TEE type = {}", self.cc_type.tee_type_str); - info!( - "TEE version = {}", - TDX_VERSION_MAP.get(&self.version).unwrap().to_owned() - ); - info!("======================================"); - } -} - -impl TcgAlgorithmRegistry for Tdx { - fn get_algorithm_id(&self) -> u8 { - self.algo_id - } -} - -impl BuildTee for Tdx {} diff --git a/common/rust/cctrusted_base/src/tee.rs b/common/rust/cctrusted_base/src/tee.rs deleted file mode 100644 index a570ca2d..00000000 --- a/common/rust/cctrusted_base/src/tee.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::cc_type::CcType; -use crate::tcg::TcgDigest; - -// holds the device node info -pub struct DeviceNode { - pub device_path: String, -} - -pub struct CcEventlogs { - //TODO -} - -// the interfaces a TEE should implement -pub trait TEE { - /*** - retrive TEE signed report - - Args: - nonce (String): against replay attacks - data (String): user data - - Returns: - the cc report byte array or error information - */ - fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error>; - - /*** - retrive TEE measurement registers, e.g.: RTMRs, vTPM PCRs, etc. - - Args: - index (u8): the index of measurement register, - algo_id (u8): the alrogithms ID - - Returns: - TcgDigest struct - */ - fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest; - - //TODO! - fn process_cc_eventlog(&self); - - fn get_cc_type(&self) -> CcType; - - //Dump confidential TEE information - fn dump(&self); -} diff --git a/common/rust/cctrusted_base/src/tpm/quote.rs b/common/rust/cctrusted_base/src/tpm/quote.rs index 5da67b2f..1ef6edf1 100644 --- a/common/rust/cctrusted_base/src/tpm/quote.rs +++ b/common/rust/cctrusted_base/src/tpm/quote.rs @@ -1,7 +1,5 @@ // return of API parse_cc_report() -pub struct TpmQuote { - // TODO -} +pub struct TpmQuote {} impl TpmQuote { pub fn parse_tpm_quote(_quote: Vec) -> Result { diff --git a/vmsdk/rust/cctrusted/src/api.rs b/vmsdk/rust/cctrusted/src/api.rs deleted file mode 100644 index f7eae01b..00000000 --- a/vmsdk/rust/cctrusted/src/api.rs +++ /dev/null @@ -1,143 +0,0 @@ -use anyhow::*; -use std::mem; -use std::result::Result; -use std::result::Result::Ok; - -use cctrusted_base::binary_blob::dump_data; -use cctrusted_base::cc_type::CcType; -use cctrusted_base::eventlog::TcgEventLog; -use cctrusted_base::tcg::{TcgDigest, ALGO_NAME_MAP}; -use cctrusted_base::tdx::quote::TdxQuote; -use cctrusted_base::tpm::quote::TpmQuote; - -use crate::api_data::*; - -/*** - Get the cc report for given nonce and data. - - The cc report is signing of attestation data (IMR values or hashes of IMR - values), made by a trusted foundation (TPM) using a key trusted by the - verifier. - - Different trusted foundation may use different cc report format. - - Args: - nonce (String): against replay attacks - data (String): user data - extraArgs: for TPM, it will be given list of IMR/PCRs - - Returns: - The cc report byte array or error information -*/ -pub fn get_cc_report( - nonce: String, - data: String, - _extra_args: ExtraArgs, -) -> Result { - match CcType::build_tee() { - Ok(mut tee) => { - // call tee trait defined methods - tee.dump(); - Ok(CcReport { - cc_report: match tee.process_cc_report(nonce, data) { - Ok(r) => r, - Err(e) => { - return Err(anyhow!("[get_cc_report] error get cc report: {:?}", e)); - } - }, - cc_type: tee.get_cc_type().tee_type as i8, - }) - } - Err(e) => return Err(anyhow!("[get_cc_report] error create tee: {:?}", e)), - } -} - -pub fn dump_cc_report(report: &Vec) { - dump_data(report) -} - -/*** - Get measurement register according to given selected index and algorithms - - Each trusted foundation in CC environment provides the multiple measurement - registers, the count is update to ``get_measurement_count()``. And for each - measurement register, it may provides multiple digest for different algorithms. - - Args: - index (u8): the index of measurement register, - algo_id (u8): the alrogithms ID - - Returns: - TcgDigest struct -*/ -pub fn get_cc_measurement(_index: u8, _algo_id: u8) -> TcgDigest { - todo!() -} - -/*** - Get eventlog for given index and count. - - TCG log in Eventlog. Verify to spoof events in the TCG log, hence defeating - remotely-attested measured-boot. - - To measure the full CC runtime environment, the eventlog may include addtional - OS type and cloud native type event beyond the measured-boot. - - Returns: - TcgEventLog struct -*/ -pub fn get_cc_eventlog(_start: u16, _count: u16) -> TcgEventLog { - todo!() -} - -/*** - Get the default Digest algorithms supported by trusted foundation. - - Different trusted foundation may support different algorithms, for example - the Intel TDX use SHA384, TPM uses SHA256. - - Beyond the default digest algorithm, some trusted foundation like TPM - may support multiple algorithms. - - Returns: - The Algorithm struct - -*/ -pub fn get_default_algorithm() -> Result { - match CcType::build_tee() { - Ok(tee) => { - // call tee trait defined methods - let algo_id = tee.get_algorithm_id(); - Ok(Algorithm { - algo_id: algo_id, - algo_id_str: ALGO_NAME_MAP.get(&algo_id).unwrap().to_owned(), - }) - } - Err(e) => { - return Err(anyhow!( - "[get_default_algorithm] error get algorithm: {:?}", - e - )) - } - } -} - -// this function parses cc report to the TDX quote struct -impl ParseCcReport for CcReport { - fn parse_cc_report(report: Vec) -> Result { - match TdxQuote::parse_tdx_quote(report) { - Ok(tdx_quote) => unsafe { - let report: &CcParsedTdxReport = mem::transmute(&tdx_quote); - Ok(report.clone()) - }, - Err(e) => return Err(anyhow!("[parse_cc_report] error parse tdx quote: {:?}", e)), - } - } -} - -// this function parses cc report to the TPM quote struct -impl ParseCcReport for CcReport { - fn parse_cc_report(_report: Vec) -> Result { - todo!() - } -} diff --git a/vmsdk/rust/cctrusted/src/api_data.rs b/vmsdk/rust/cctrusted/src/api_data.rs deleted file mode 100644 index c5d08047..00000000 --- a/vmsdk/rust/cctrusted/src/api_data.rs +++ /dev/null @@ -1,65 +0,0 @@ -/*** - ************************************ - * API get_cc_report() related data * - ************************************ - */ - -// input of API get_cc_report() -// this struct is used in vTPM and other TEE scenarios -// e.g.: vTPM may need report based on selective PCRs -pub struct ExtraArgs {} - -pub const TYPE_PLAIN: i8 = -1; -pub const TYPE_TPM: i8 = 0; -pub const TYPE_TDX: i8 = 1; -pub const TYPE_SEV: i8 = 2; -pub const TYPE_CCA: i8 = 3; - -// return of API get_cc_report() -pub struct CcReport { - pub cc_report: Vec, - pub cc_type: i8, -} - -/*** - ************************************** - * API parse_cc_report() related data * - ************************************** - */ -// return of API parse_cc_report() in TDX case -#[derive(Clone)] -pub struct CcParsedTdxReport { - pub dummy_var1: u8, - pub dummy_var2: u8, -} - -// return of API parse_cc_report() in TPM case -pub struct CcParsedTpmReport {} - -/*** - trait to be implemented for cc report parsing. - - the cooresponding implementation of parse_cc_report will be called according to - intented return format and the return of the trait function depends on - the type of cc report, e.g.: TdxQuote, TpmQuote and etc. - - TDX quote parsing Example: - if following is provided: - let tdx_quote: TdxQuote = parse_cc_report(cc_report_str); - then this implementation in api.rs will be called: - fn parse_cc_report(report: Vec) -> Result; -*/ -pub trait ParseCcReport { - fn parse_cc_report(_report: Vec) -> Result; -} - -/*** - ******************************************** - * API get_default_algorithm() related data * - ******************************************** - */ -// return structure for get_default_algorithm -pub struct Algorithm { - pub algo_id: u8, - pub algo_id_str: String, -} diff --git a/vmsdk/rust/cctrusted/src/lib.rs b/vmsdk/rust/cctrusted/src/lib.rs deleted file mode 100644 index 08b00c1a..00000000 --- a/vmsdk/rust/cctrusted/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod api; -pub mod api_data; diff --git a/vmsdk/rust/cctrusted/Cargo.toml b/vmsdk/rust/cctrusted_vm/Cargo.toml similarity index 70% rename from vmsdk/rust/cctrusted/Cargo.toml rename to vmsdk/rust/cctrusted_vm/Cargo.toml index 3e393a60..d3ed5dc6 100644 --- a/vmsdk/rust/cctrusted/Cargo.toml +++ b/vmsdk/rust/cctrusted_vm/Cargo.toml @@ -1,13 +1,15 @@ [package] -name = "cctrusted" +name = "cctrusted_vm" version = "0.1.0" edition = "2021" [lib] -name = "cctrusted" +name = "cctrusted_vm" path = "src/lib.rs" [dependencies] cctrusted_base = { path = "../../../common/rust/cctrusted_base" } anyhow = "1.0" log = "0.4.20" +nix = "0.26.2" +base64 = "0.13.0" diff --git a/vmsdk/rust/cctrusted_vm/src/cvm.rs b/vmsdk/rust/cctrusted_vm/src/cvm.rs new file mode 100644 index 00000000..3d10d20e --- /dev/null +++ b/vmsdk/rust/cctrusted_vm/src/cvm.rs @@ -0,0 +1,100 @@ +use crate::tdvm::TdxVM; +use anyhow::*; +use cctrusted_base::cc_type::*; +use cctrusted_base::tcg::{TcgAlgorithmRegistry, TcgDigest}; +use std::path::Path; + +// the interfaces a CVM should implement +pub trait CVM { + /*** + retrive CVM signed report + + Args: + nonce (String): against replay attacks + data (String): user data + + Returns: + the cc report byte array or error information + */ + fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error>; + + /*** + retrive CVM measurement registers, e.g.: RTMRs, vTPM PCRs, etc. + + Args: + index (u8): the index of measurement register, + algo_id (u8): the alrogithms ID + + Returns: + TcgDigest struct + */ + fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest; + + /*** + retrive CVM eventlogs + + Args: + start and count of eventlogs + + Returns: + array of eventlogs + */ + fn process_cc_eventlog(&self); + + /*** + retrive CVM type + + Args: + None + + Returns: + CcType of CVM + */ + fn get_cc_type(&self) -> CcType; + + //Dump confidential CVM information + fn dump(&self); +} + +// used for return of Boxed trait object in build_cvm() +// this composed trait includes functions in both trait CVM and trait TcgAlgorithmRegistry +pub trait BuildCVM: CVM + TcgAlgorithmRegistry {} + +// holds the device node info +pub struct DeviceNode { + pub device_path: String, +} + +/*** + instance a specific object containers specific CVM methods + and desired trait functions specified by "dyn BuildCVM" +*/ +pub fn build_cvm() -> Result, anyhow::Error> { + // instance a CVM according to detected TEE type + match get_cvm_type().tee_type { + TeeType::TDX => Ok(Box::new(TdxVM::new())), + TeeType::SEV => todo!(), + TeeType::CCA => todo!(), + TeeType::TPM => todo!(), + TeeType::PLAIN => return Err(anyhow!("[build_cvm] Error: not in any TEE!")), + } +} + +// detect CVM type +pub fn get_cvm_type() -> CcType { + let mut tee_type = TeeType::PLAIN; + if Path::new(TEE_TPM_PATH).exists() { + tee_type = TeeType::TPM; + } else if Path::new(TEE_TDX_1_0_PATH).exists() || Path::new(TEE_TDX_1_5_PATH).exists() { + tee_type = TeeType::TDX; + } else if Path::new(TEE_SEV_PATH).exists() { + tee_type = TeeType::SEV; + } else { + // TODO add support for CCA and etc. + } + + CcType { + tee_type: tee_type.clone(), + tee_type_str: TEE_NAME_MAP.get(&tee_type).unwrap().to_owned(), + } +} diff --git a/vmsdk/rust/cctrusted_vm/src/lib.rs b/vmsdk/rust/cctrusted_vm/src/lib.rs new file mode 100644 index 00000000..5fcc9b0f --- /dev/null +++ b/vmsdk/rust/cctrusted_vm/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cvm; +pub mod sdk; +pub mod tdvm; diff --git a/vmsdk/rust/cctrusted_vm/src/sdk.rs b/vmsdk/rust/cctrusted_vm/src/sdk.rs new file mode 100644 index 00000000..a8939fd9 --- /dev/null +++ b/vmsdk/rust/cctrusted_vm/src/sdk.rs @@ -0,0 +1,74 @@ +use anyhow::*; +use core::result::Result; +use core::result::Result::Ok; + +use cctrusted_base::binary_blob::dump_data; +use cctrusted_base::eventlog::TcgEventLog; +use cctrusted_base::tcg::{TcgDigest, ALGO_NAME_MAP}; + +use crate::cvm::build_cvm; +use cctrusted_base::api::*; +use cctrusted_base::api_data::*; + +pub struct API {} + +impl CCTrustedApi for API { + // CCTrustedApi trait function: get report of a CVM + fn get_cc_report( + nonce: String, + data: String, + _extra_args: ExtraArgs, + ) -> Result { + match build_cvm() { + Ok(mut cvm) => { + // call CVM trait defined methods + cvm.dump(); + Ok(CcReport { + cc_report: match cvm.process_cc_report(nonce, data) { + Ok(r) => r, + Err(e) => { + return Err(anyhow!("[get_cc_report] error get cc report: {:?}", e)); + } + }, + cc_type: cvm.get_cc_type().tee_type, + }) + } + Err(e) => return Err(anyhow!("[get_cc_report] error create cvm: {:?}", e)), + } + } + + // CCTrustedApi trait function: dump report of a CVM in hex and char format + fn dump_cc_report(report: &Vec) { + dump_data(report) + } + + // CCTrustedApi trait function: get measurements of a CVM + fn get_cc_measurement(_index: u8, _algo_id: u8) -> TcgDigest { + todo!() + } + + // CCTrustedApi trait function: get eventlogs of a CVM + fn get_cc_eventlog(_start: u16, _count: u16) -> TcgEventLog { + todo!() + } + + // CCTrustedApi trait function: get default algorithm of a CVM + fn get_default_algorithm() -> Result { + match build_cvm() { + Ok(cvm) => { + // call CVM trait defined methods + let algo_id = cvm.get_algorithm_id(); + Ok(Algorithm { + algo_id: algo_id, + algo_id_str: ALGO_NAME_MAP.get(&algo_id).unwrap().to_owned(), + }) + } + Err(e) => { + return Err(anyhow!( + "[get_default_algorithm] error get algorithm: {:?}", + e + )) + } + } + } +} diff --git a/vmsdk/rust/cctrusted_vm/src/tdvm.rs b/vmsdk/rust/cctrusted_vm/src/tdvm.rs new file mode 100644 index 00000000..f17f1692 --- /dev/null +++ b/vmsdk/rust/cctrusted_vm/src/tdvm.rs @@ -0,0 +1,352 @@ +#![allow(non_camel_case_types)] + +use crate::cvm::*; +use anyhow::*; +use cctrusted_base::cc_type::*; +use cctrusted_base::tcg::{TcgAlgorithmRegistry, TcgDigest}; +use cctrusted_base::tdx::common::*; +use cctrusted_base::tdx::quote::*; +use cctrusted_base::tdx::report::*; +use core::convert::TryInto; +use core::mem; +use core::ptr; +use core::result::Result; +use core::result::Result::Ok; +use log::info; +use nix::*; +use std::fs::File; +use std::os::fd::AsRawFd; +use std::path::Path; + +// TDX ioctl operation code to be used for get TDX quote and TD Report +pub enum TdxOperation { + TDX_GET_TD_REPORT = 1, + TDX_1_0_GET_QUOTE = 2, + TDX_1_5_GET_QUOTE = 4, +} + +/* + TdxVM is an abstraction of TDX running environment, it contains: + cc_type: should always be CcType built with TeeType::TDX + version: TdxVersion::TDX_1_0 or TdxVersion::TDX_1_5 + device_node: /dev/tdx-guest or /dev/tdx_guest + algo_id: should be TPM_ALG_SHA384 +*/ +pub struct TdxVM { + pub cc_type: CcType, + pub version: TdxVersion, + pub device_node: DeviceNode, + pub algo_id: u8, +} + +// implement the structure method and associated function +impl TdxVM { + // TdxVM struct associated function: to build a TdxVM sturcture instance + pub fn new() -> TdxVM { + let cc_type = CcType { + tee_type: TeeType::TDX, + tee_type_str: TEE_NAME_MAP.get(&TeeType::TDX).unwrap().to_owned(), + }; + + let version = Self::get_tdx_version(); + let device_node = DeviceNode { + device_path: TDX_DEVICE_NODE_MAP.get(&version).unwrap().to_owned(), + }; + let algo_id = cctrusted_base::tcg::TPM_ALG_SHA384; + + TdxVM { + cc_type, + version, + device_node, + algo_id, + } + } + + // TdxVM struct method: get tdreport + pub fn get_td_report(&self, nonce: String, data: String) -> Result, anyhow::Error> { + let report_data = match Tdx::generate_tdx_report_data(nonce, Some(data)) { + Ok(r) => r, + Err(e) => { + return Err(anyhow!( + "[get_td_report] error generating TDX report data: {:?}", + e + )) + } + }; + + let device_node = match File::options() + .read(true) + .write(true) + .open(self.device_node.device_path.clone()) + { + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to open {}: {:?}", + self.device_node.device_path, + e + )) + } + Ok(fd) => fd, + }; + + match self.version { + TdxVersion::TDX_1_0 => { + let report_data_bytes = match base64::decode(report_data) { + Ok(v) => v, + Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), + }; + + //prepare get TDX report request data + let mut report_data_array: [u8; REPORT_DATA_LEN as usize] = + [0; REPORT_DATA_LEN as usize]; + report_data_array.copy_from_slice(&report_data_bytes[0..]); + let td_report: [u8; TDX_REPORT_LEN as usize] = [0; TDX_REPORT_LEN as usize]; + + //build the request + let request = tdx_1_0_report_req { + subtype: 0 as u8, + reportdata: ptr::addr_of!(report_data_array) as u64, + rpd_len: REPORT_DATA_LEN, + tdreport: ptr::addr_of!(td_report) as u64, + tdr_len: TDX_REPORT_LEN, + }; + + //build the operator code + ioctl_readwrite!( + get_report_1_0_ioctl, + b'T', + TdxOperation::TDX_GET_TD_REPORT, + u64 + ); + + //apply the ioctl command + match unsafe { + get_report_1_0_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(request) as *mut u64, + ) + } { + Err(e) => { + return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)) + } + Ok(_) => (), + }; + + Ok(td_report.to_vec()) + } + TdxVersion::TDX_1_5 => { + let report_data_bytes = match base64::decode(report_data) { + Ok(v) => v, + Err(e) => return Err(anyhow!("report data is not base64 encoded: {:?}", e)), + }; + + //prepare get TDX report request data + let mut request = tdx_1_5_report_req { + reportdata: [0; REPORT_DATA_LEN as usize], + tdreport: [0; TDX_REPORT_LEN as usize], + }; + request.reportdata.copy_from_slice(&report_data_bytes[0..]); + + //build the operator code + ioctl_readwrite!( + get_report_1_5_ioctl, + b'T', + TdxOperation::TDX_GET_TD_REPORT, + tdx_1_5_report_req + ); + + //apply the ioctl command + match unsafe { + get_report_1_5_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(request) as *mut tdx_1_5_report_req, + ) + } { + Err(e) => { + return Err(anyhow!("[get_td_report] Fail to get TDX report: {:?}", e)) + } + Ok(_) => (), + }; + + Ok(request.tdreport.to_vec()) + } + } + } + + // TdxVM struct associated function: detect the TDX version + fn get_tdx_version() -> TdxVersion { + if Path::new(TEE_TDX_1_0_PATH).exists() { + TdxVersion::TDX_1_0 + } else if Path::new(TEE_TDX_1_5_PATH).exists() { + TdxVersion::TDX_1_5 + } else { + TdxVersion::TDX_1_0 + } + } +} + +// TdxVM implements the interfaces defined in CVM trait +impl CVM for TdxVM { + // CVM trait function: get tdx quote + fn process_cc_report(&mut self, nonce: String, data: String) -> Result, anyhow::Error> { + let tdreport = match self.get_td_report(nonce, data) { + Ok(r) => r, + Err(e) => { + return Err(anyhow!( + "[process_cc_report] error getting TD report: {:?}", + e + )) + } + }; + + let report_data_array: [u8; TDX_REPORT_LEN as usize] = match tdreport.try_into() { + Ok(r) => r, + Err(e) => return Err(anyhow!("[get_tdx_quote] Wrong TDX report format: {:?}", e)), + }; + + //build QGS request message + let qgs_msg = Tdx::generate_qgs_quote_msg(report_data_array); + + //build quote generation request header + let mut quote_header = tdx_quote_hdr { + version: 1, + status: 0, + in_len: (mem::size_of_val(&qgs_msg) + 4) as u32, + out_len: 0, + data_len_be_bytes: (1048 as u32).to_be_bytes(), + data: [0; TDX_QUOTE_LEN as usize], + }; + + let qgs_msg_bytes = unsafe { + let ptr = &qgs_msg as *const qgs_msg_get_quote_req as *const u8; + core::slice::from_raw_parts(ptr, mem::size_of::()) + }; + quote_header.data[0..(16 + 8 + TDX_REPORT_LEN) as usize] + .copy_from_slice(&qgs_msg_bytes[0..((16 + 8 + TDX_REPORT_LEN) as usize)]); + + let tdx_quote_request = tdx_quote_req { + buf: ptr::addr_of!(quote_header) as u64, + len: TDX_QUOTE_LEN as u64, + }; + + let device_node = match File::options() + .read(true) + .write(true) + .open(self.device_node.device_path.clone()) + { + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to open {}: {:?}", + self.device_node.device_path, + e + )) + } + Ok(fd) => fd, + }; + + //build the operator code and apply the ioctl command + match self.version { + TdxVersion::TDX_1_0 => { + ioctl_read!( + get_quote_1_0_ioctl, + b'T', + TdxOperation::TDX_1_0_GET_QUOTE, + u64 + ); + match unsafe { + get_quote_1_0_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(tdx_quote_request) as *mut u64, + ) + } { + Err(e) => { + return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) + } + Ok(_r) => _r, + }; + } + TdxVersion::TDX_1_5 => { + ioctl_read!( + get_quote_1_5_ioctl, + b'T', + TdxOperation::TDX_1_5_GET_QUOTE, + tdx_quote_req + ); + match unsafe { + get_quote_1_5_ioctl( + device_node.as_raw_fd(), + ptr::addr_of!(tdx_quote_request) as *mut tdx_quote_req, + ) + } { + Err(e) => { + return Err(anyhow!("[get_tdx_quote] Fail to get TDX quote: {:?}", e)) + } + Ok(_r) => _r, + }; + } + }; + + //inspect the response and retrive quote data + let out_len = quote_header.out_len; + let qgs_msg_resp_size = + unsafe { core::mem::transmute::<[u8; 4], u32>(quote_header.data_len_be_bytes) }.to_be(); + + let qgs_msg_resp = unsafe { + let raw_ptr = ptr::addr_of!(quote_header.data) as *mut qgs_msg_get_quote_resp; + raw_ptr.as_mut().unwrap() as &mut qgs_msg_get_quote_resp + }; + + if out_len - qgs_msg_resp_size != 4 { + return Err(anyhow!( + "[get_tdx_quote] Fail to get TDX quote: wrong TDX quote size!" + )); + } + + if qgs_msg_resp.header.major_version != 1 + || qgs_msg_resp.header.minor_version != 0 + || qgs_msg_resp.header.msg_type != 1 + || qgs_msg_resp.header.error_code != 0 + { + return Err(anyhow!( + "[get_tdx_quote] Fail to get TDX quote: QGS response error!" + )); + } + + Ok(qgs_msg_resp.id_quote[0..(qgs_msg_resp.quote_size as usize)].to_vec()) + } + + // CVM trait function: retrieve TDX RTMR + fn process_cc_measurement(&self, _index: u8, _algo_id: u8) -> TcgDigest { + todo!() + } + + // CVM trait function: retrieve TDX CCEL and IMA eventlog + fn process_cc_eventlog(&self) -> () { + todo!() + } + + // CVM trait function: retrive CVM type + fn get_cc_type(&self) -> CcType { + return self.cc_type.clone(); + } + + // CVM trait function: dump CVM basic information + fn dump(&self) { + info!("======================================"); + info!("CVM type = {}", self.cc_type.tee_type_str); + info!( + "CVM version = {}", + TDX_VERSION_MAP.get(&self.version).unwrap().to_owned() + ); + info!("======================================"); + } +} + +impl TcgAlgorithmRegistry for TdxVM { + // TcgAlgorithmRegistry trait function: return CVM default algorithm ID + fn get_algorithm_id(&self) -> u8 { + self.algo_id + } +} + +impl BuildCVM for TdxVM {} diff --git a/vmsdk/rust/sample/Cargo.toml b/vmsdk/rust/sample/Cargo.toml index bf76d984..4154b6d5 100644 --- a/vmsdk/rust/sample/Cargo.toml +++ b/vmsdk/rust/sample/Cargo.toml @@ -8,7 +8,8 @@ name = "cc-sample" path = "src/cc-sample.rs" [dependencies] -cctrusted = { path = "../cctrusted" } +cctrusted_vm = { path = "../cctrusted_vm" } +cctrusted_base = { path = "../../../common/rust/cctrusted_base" } anyhow = "1.0" log = "0.4.20" -env_logger = "0.10.0" +env_logger = "0.10.1" \ No newline at end of file diff --git a/vmsdk/rust/sample/src/cc-sample.rs b/vmsdk/rust/sample/src/cc-sample.rs index a5fe8944..c66cfeb1 100644 --- a/vmsdk/rust/sample/src/cc-sample.rs +++ b/vmsdk/rust/sample/src/cc-sample.rs @@ -1,5 +1,8 @@ -use cctrusted::api::*; -use cctrusted::api_data::*; +use cctrusted_base::api::*; +use cctrusted_base::api_data::*; +use cctrusted_base::cc_type::TeeType; +use cctrusted_base::tdx::quote::TdxQuote; +use cctrusted_vm::sdk::API; use log::*; fn main() { @@ -11,7 +14,7 @@ fn main() { // retrieve cc report with API "get_cc_report" info!("call cc trusted API [get_cc_report] to retrieve cc report!"); - let report = match get_cc_report(nonce, data, ExtraArgs {}) { + let report = match API::get_cc_report(nonce, data, ExtraArgs {}) { Ok(q) => q, Err(e) => { error!("error getting TDX report: {:?}", e); @@ -21,11 +24,11 @@ fn main() { // dump the cc report with API "dump_cc_report" info!("call cc trusted API [dump_cc_report] to dump cc report!"); - dump_cc_report(&report.cc_report); + API::dump_cc_report(&report.cc_report); // parse the cc report with API "parse_cc_report" - if report.cc_type == TYPE_TDX { - let tdx_quote: CcParsedTdxReport = match CcReport::parse_cc_report(report.cc_report) { + if report.cc_type == TeeType::TDX { + let tdx_quote: TdxQuote = match CcReport::parse_cc_report(report.cc_report) { Ok(q) => q, Err(e) => { error!("error parse tdx quote: {:?}", e); @@ -38,9 +41,9 @@ fn main() { ); } - // get TEE default algorithm with API "get_default_algorithm" - info!("call cc trusted API [get_default_algorithm] to get TEE supported algorithm!"); - match get_default_algorithm() { + // get CVM default algorithm with API "get_default_algorithm" + info!("call cc trusted API [get_default_algorithm] to get CVM supported algorithm!"); + match API::get_default_algorithm() { Ok(algorithm) => { info!("supported algorithm: {}", algorithm.algo_id_str); (); From 3237aa346ca4d8d3924371180cb12e9ef16ac3f5 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 14:23:16 +0800 Subject: [PATCH 05/12] updates according to review comments: - add github action for rust check - add license and lincense check - update code format according to rust code check feedback --- .github/workflows/pr-check-rust.yaml | 53 +++++++++++++++++++ common/rust/cctrusted_base/Cargo.toml | 1 + common/rust/cctrusted_base/deny.toml | 35 ++++++++++++ common/rust/cctrusted_base/src/api.rs | 4 +- common/rust/cctrusted_base/src/binary_blob.rs | 14 ++--- common/rust/cctrusted_base/src/tdx/quote.rs | 2 +- common/rust/cctrusted_base/src/tdx/rtmr.rs | 4 +- vmsdk/rust/cctrusted_vm/Cargo.toml | 1 + vmsdk/rust/cctrusted_vm/deny.toml | 35 ++++++++++++ vmsdk/rust/cctrusted_vm/src/cvm.rs | 4 +- vmsdk/rust/cctrusted_vm/src/sdk.rs | 16 +++--- vmsdk/rust/cctrusted_vm/src/tdvm.rs | 12 ++--- vmsdk/rust/sample/Cargo.toml | 5 +- vmsdk/rust/sample/src/cc-sample.rs | 42 ++++----------- 14 files changed, 165 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/pr-check-rust.yaml create mode 100644 common/rust/cctrusted_base/deny.toml create mode 100644 vmsdk/rust/cctrusted_vm/deny.toml diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml new file mode 100644 index 00000000..3634b56f --- /dev/null +++ b/.github/workflows/pr-check-rust.yaml @@ -0,0 +1,53 @@ +name: Rust Code Scan + +on: + push: + branches: + - main + paths: + - 'common/rust/cctrusted_base/src/**.rs' + - 'common/rust/cctrusted_base/src/tdx/**.rs' + - 'common/rust/cctrusted_base/src/tpm/**.rs' + - 'vmsdk/rust/cctrusted_vm/src/**.rs' + - 'vmsdk/rust/sample/src/**.rs' + - '.github/workflows/pr-check-rust.yaml' + pull_request: + paths: + - 'common/rust/cctrusted_base/src/**.rs' + - 'common/rust/cctrusted_base/src/tdx/**.rs' + - 'common/rust/cctrusted_base/src/tpm/**.rs' + - 'vmsdk/rust/cctrusted_vm/src/**.rs' + - 'vmsdk/rust/sample/src/**.rs' + - '.github/workflows/pr-check-rust.yaml' + workflow_dispatch: + +jobs: + codescan: + runs-on: tdx-runner + steps: + - name: Checkout PR + uses: actions/checkout@v3 + + - name: Set up Rust action + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.70.0 + + - name: Install dependencies + run: | + sudo apt update && yes | DEBIAN_FRONTEND=noninteractive sudo apt install -y libcryptsetup-dev clang protobuf-compiler protobuf-c-compiler libprotobuf-c-dev libprotobuf-c1 build-essential pkg-config libssl-dev + - name: Run cargo check + run: | + cd common/rust/cctrusted_base/src + cargo test + cargo check + cargo fmt -- --check + cargo clippy + cargo install --locked cargo-deny + cargo deny check + cd vmsdk/rust/cctrusted_vm/src/ + cargo test + cargo check + cargo fmt -- --check + cargo clippy + cargo deny check \ No newline at end of file diff --git a/common/rust/cctrusted_base/Cargo.toml b/common/rust/cctrusted_base/Cargo.toml index 91e97766..51cf0d5a 100644 --- a/common/rust/cctrusted_base/Cargo.toml +++ b/common/rust/cctrusted_base/Cargo.toml @@ -2,6 +2,7 @@ name = "cctrusted_base" version = "0.1.0" edition = "2021" +license = "Apache-2.0" [lib] name = "cctrusted_base" diff --git a/common/rust/cctrusted_base/deny.toml b/common/rust/cctrusted_base/deny.toml new file mode 100644 index 00000000..6e656f7e --- /dev/null +++ b/common/rust/cctrusted_base/deny.toml @@ -0,0 +1,35 @@ +[advisories] +vulnerability = "deny" +unmaintained = "warn" +yanked = "warn" +notice = "warn" + +[licenses] +unlicensed = "warn" +allow = [ + "MIT", + "Apache-2.0", + "ISC", + "BSD-3-Clause", + "Unicode-DFS-2016", +] + +copyleft = "warn" +allow-osi-fsf-free = "neither" +default = "deny" +confidence-threshold = 0.8 + +[[licenses.clarify]] +name = "ring" +expression = "MIT AND ISC AND OpenSSL" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 } +] + +[bans] +multiple-versions = "warn" +wildcards = "allow" + +[sources] +unknown-registry = "warn" +unknown-git = "warn" \ No newline at end of file diff --git a/common/rust/cctrusted_base/src/api.rs b/common/rust/cctrusted_base/src/api.rs index e97b3c4d..507e7c08 100644 --- a/common/rust/cctrusted_base/src/api.rs +++ b/common/rust/cctrusted_base/src/api.rs @@ -115,7 +115,7 @@ impl ParseCcReport for CcReport { let report: &TdxQuote = mem::transmute(&tdx_quote); Ok(report.clone()) }, - Err(e) => return Err(anyhow!("[parse_cc_report] error parse tdx quote: {:?}", e)), + Err(e) => Err(anyhow!("[parse_cc_report] error parse tdx quote: {:?}", e)), } } } @@ -125,4 +125,4 @@ impl ParseCcReport for CcReport { fn parse_cc_report(_report: Vec) -> Result { todo!() } -} +} \ No newline at end of file diff --git a/common/rust/cctrusted_base/src/binary_blob.rs b/common/rust/cctrusted_base/src/binary_blob.rs index 88dadbb3..31738abf 100644 --- a/common/rust/cctrusted_base/src/binary_blob.rs +++ b/common/rust/cctrusted_base/src/binary_blob.rs @@ -22,9 +22,9 @@ pub fn dump_data(data: &Vec) { '~', '"', '!', ]; - while usize::from(index) < data.len() { + while index < data.len() { if index % 16 == 0 { - if printstr.len() != 0 { + if !printstr.is_empty() { info!("{} {}", linestr, printstr); printstr = "".to_string(); } @@ -35,13 +35,13 @@ pub fn dump_data(data: &Vec) { linestr.push_str(format!("{:02X} ", v).as_str()); match printable.iter().position(|&c| c == (v as char)) { Some(_) => { - if v < 0x9 || v > 0xD { + if !(0x9..=0xD).contains(&v) { printstr.push_str(core::str::from_utf8(&[v]).unwrap()); } else { - printstr.push_str("."); + printstr.push('.'); } } - None => printstr.push_str("."), + None => printstr.push('.'), } index += 1; @@ -53,7 +53,7 @@ pub fn dump_data(data: &Vec) { blank.push_str(" "); } info!("{}{} {}", linestr, blank, printstr); - } else if usize::from(index) == data.len() { + } else if index == data.len() { info!("{} {}", linestr, printstr); } -} +} \ No newline at end of file diff --git a/common/rust/cctrusted_base/src/tdx/quote.rs b/common/rust/cctrusted_base/src/tdx/quote.rs index 9f81fc3d..40edd4f1 100644 --- a/common/rust/cctrusted_base/src/tdx/quote.rs +++ b/common/rust/cctrusted_base/src/tdx/quote.rs @@ -92,4 +92,4 @@ impl TdxQuote { dummy_var2: 2, }) } -} +} \ No newline at end of file diff --git a/common/rust/cctrusted_base/src/tdx/rtmr.rs b/common/rust/cctrusted_base/src/tdx/rtmr.rs index e0cc9c6c..3c9a0134 100644 --- a/common/rust/cctrusted_base/src/tdx/rtmr.rs +++ b/common/rust/cctrusted_base/src/tdx/rtmr.rs @@ -9,7 +9,7 @@ pub struct TdxRTMR { impl TcgIMR for TdxRTMR { fn max_index(&self) -> u8 { - return 3; + 3 } fn get_index(&self) -> u8 { @@ -23,4 +23,4 @@ impl TcgIMR for TdxRTMR { fn is_valid(&self) -> bool { todo!() } -} +} \ No newline at end of file diff --git a/vmsdk/rust/cctrusted_vm/Cargo.toml b/vmsdk/rust/cctrusted_vm/Cargo.toml index d3ed5dc6..35a0aa7a 100644 --- a/vmsdk/rust/cctrusted_vm/Cargo.toml +++ b/vmsdk/rust/cctrusted_vm/Cargo.toml @@ -2,6 +2,7 @@ name = "cctrusted_vm" version = "0.1.0" edition = "2021" +license = "Apache-2.0" [lib] name = "cctrusted_vm" diff --git a/vmsdk/rust/cctrusted_vm/deny.toml b/vmsdk/rust/cctrusted_vm/deny.toml new file mode 100644 index 00000000..6e656f7e --- /dev/null +++ b/vmsdk/rust/cctrusted_vm/deny.toml @@ -0,0 +1,35 @@ +[advisories] +vulnerability = "deny" +unmaintained = "warn" +yanked = "warn" +notice = "warn" + +[licenses] +unlicensed = "warn" +allow = [ + "MIT", + "Apache-2.0", + "ISC", + "BSD-3-Clause", + "Unicode-DFS-2016", +] + +copyleft = "warn" +allow-osi-fsf-free = "neither" +default = "deny" +confidence-threshold = 0.8 + +[[licenses.clarify]] +name = "ring" +expression = "MIT AND ISC AND OpenSSL" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 } +] + +[bans] +multiple-versions = "warn" +wildcards = "allow" + +[sources] +unknown-registry = "warn" +unknown-git = "warn" \ No newline at end of file diff --git a/vmsdk/rust/cctrusted_vm/src/cvm.rs b/vmsdk/rust/cctrusted_vm/src/cvm.rs index 3d10d20e..975ef031 100644 --- a/vmsdk/rust/cctrusted_vm/src/cvm.rs +++ b/vmsdk/rust/cctrusted_vm/src/cvm.rs @@ -76,7 +76,7 @@ pub fn build_cvm() -> Result, anyhow::Error> { TeeType::SEV => todo!(), TeeType::CCA => todo!(), TeeType::TPM => todo!(), - TeeType::PLAIN => return Err(anyhow!("[build_cvm] Error: not in any TEE!")), + TeeType::PLAIN => Err(anyhow!("[build_cvm] Error: not in any TEE!")), } } @@ -97,4 +97,4 @@ pub fn get_cvm_type() -> CcType { tee_type: tee_type.clone(), tee_type_str: TEE_NAME_MAP.get(&tee_type).unwrap().to_owned(), } -} +} \ No newline at end of file diff --git a/vmsdk/rust/cctrusted_vm/src/sdk.rs b/vmsdk/rust/cctrusted_vm/src/sdk.rs index a8939fd9..ae034b1c 100644 --- a/vmsdk/rust/cctrusted_vm/src/sdk.rs +++ b/vmsdk/rust/cctrusted_vm/src/sdk.rs @@ -33,7 +33,7 @@ impl CCTrustedApi for API { cc_type: cvm.get_cc_type().tee_type, }) } - Err(e) => return Err(anyhow!("[get_cc_report] error create cvm: {:?}", e)), + Err(e) => Err(anyhow!("[get_cc_report] error create cvm: {:?}", e)), } } @@ -59,16 +59,14 @@ impl CCTrustedApi for API { // call CVM trait defined methods let algo_id = cvm.get_algorithm_id(); Ok(Algorithm { - algo_id: algo_id, + algo_id, algo_id_str: ALGO_NAME_MAP.get(&algo_id).unwrap().to_owned(), }) } - Err(e) => { - return Err(anyhow!( - "[get_default_algorithm] error get algorithm: {:?}", - e - )) - } + Err(e) => Err(anyhow!( + "[get_default_algorithm] error get algorithm: {:?}", + e + )), } } -} +} \ No newline at end of file diff --git a/vmsdk/rust/cctrusted_vm/src/tdvm.rs b/vmsdk/rust/cctrusted_vm/src/tdvm.rs index f17f1692..fd136b7d 100644 --- a/vmsdk/rust/cctrusted_vm/src/tdvm.rs +++ b/vmsdk/rust/cctrusted_vm/src/tdvm.rs @@ -104,7 +104,7 @@ impl TdxVM { //build the request let request = tdx_1_0_report_req { - subtype: 0 as u8, + subtype: 0_u8, reportdata: ptr::addr_of!(report_data_array) as u64, rpd_len: REPORT_DATA_LEN, tdreport: ptr::addr_of!(td_report) as u64, @@ -213,8 +213,8 @@ impl CVM for TdxVM { status: 0, in_len: (mem::size_of_val(&qgs_msg) + 4) as u32, out_len: 0, - data_len_be_bytes: (1048 as u32).to_be_bytes(), - data: [0; TDX_QUOTE_LEN as usize], + data_len_be_bytes: (1048_u32).to_be_bytes(), + data: [0; TDX_QUOTE_LEN], }; let qgs_msg_bytes = unsafe { @@ -321,13 +321,13 @@ impl CVM for TdxVM { } // CVM trait function: retrieve TDX CCEL and IMA eventlog - fn process_cc_eventlog(&self) -> () { + fn process_cc_eventlog(&self) { todo!() } // CVM trait function: retrive CVM type fn get_cc_type(&self) -> CcType { - return self.cc_type.clone(); + self.cc_type.clone() } // CVM trait function: dump CVM basic information @@ -349,4 +349,4 @@ impl TcgAlgorithmRegistry for TdxVM { } } -impl BuildCVM for TdxVM {} +impl BuildCVM for TdxVM {} \ No newline at end of file diff --git a/vmsdk/rust/sample/Cargo.toml b/vmsdk/rust/sample/Cargo.toml index 4154b6d5..6afefc97 100644 --- a/vmsdk/rust/sample/Cargo.toml +++ b/vmsdk/rust/sample/Cargo.toml @@ -2,6 +2,7 @@ name = "cctrusted-sample" version = "0.1.0" edition = "2021" +license = "Apache-2.0" [[bin]] name = "cc-sample" @@ -12,4 +13,6 @@ cctrusted_vm = { path = "../cctrusted_vm" } cctrusted_base = { path = "../../../common/rust/cctrusted_base" } anyhow = "1.0" log = "0.4.20" -env_logger = "0.10.1" \ No newline at end of file +env_logger = "0.10.1" +base64 = "0.13.0" +rand = "0.8.5" \ No newline at end of file diff --git a/vmsdk/rust/sample/src/cc-sample.rs b/vmsdk/rust/sample/src/cc-sample.rs index c66cfeb1..38c39403 100644 --- a/vmsdk/rust/sample/src/cc-sample.rs +++ b/vmsdk/rust/sample/src/cc-sample.rs @@ -1,16 +1,20 @@ use cctrusted_base::api::*; use cctrusted_base::api_data::*; -use cctrusted_base::cc_type::TeeType; -use cctrusted_base::tdx::quote::TdxQuote; use cctrusted_vm::sdk::API; use log::*; +use rand::Rng; fn main() { // set log level env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - let nonce = "MTIzNDU2Nzg=".to_string(); - let data = "YWJjZGVmZw==".to_string(); + /*** + * Note: in real user case, the nonce should come from attestation server + * side to prevent replay attack and the data should be generate by API caller + * according to user define spec + */ + let nonce = base64::encode(rand::thread_rng().gen::<[u8; 32]>()); + let data = base64::encode(rand::thread_rng().gen::<[u8; 32]>()); // retrieve cc report with API "get_cc_report" info!("call cc trusted API [get_cc_report] to retrieve cc report!"); @@ -25,32 +29,4 @@ fn main() { // dump the cc report with API "dump_cc_report" info!("call cc trusted API [dump_cc_report] to dump cc report!"); API::dump_cc_report(&report.cc_report); - - // parse the cc report with API "parse_cc_report" - if report.cc_type == TeeType::TDX { - let tdx_quote: TdxQuote = match CcReport::parse_cc_report(report.cc_report) { - Ok(q) => q, - Err(e) => { - error!("error parse tdx quote: {:?}", e); - return; - } - }; - info!( - "dummy_var1 = {}, dummy_var2 = {}", - tdx_quote.dummy_var1, tdx_quote.dummy_var2 - ); - } - - // get CVM default algorithm with API "get_default_algorithm" - info!("call cc trusted API [get_default_algorithm] to get CVM supported algorithm!"); - match API::get_default_algorithm() { - Ok(algorithm) => { - info!("supported algorithm: {}", algorithm.algo_id_str); - (); - } - Err(e) => { - error!("error get algorithm: {:?}", e); - return; - } - }; -} +} \ No newline at end of file From c18b69a8b6e64c39b11dd6eb07af433dda6ef7bb Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 14:53:48 +0800 Subject: [PATCH 06/12] rust github action: update rust toolchain --- .github/workflows/pr-check-rust.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index 3634b56f..a101de89 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -31,7 +31,7 @@ jobs: - name: Set up Rust action uses: actions-rs/toolchain@v1 with: - toolchain: 1.70.0 + toolchain: nightly - name: Install dependencies run: | From ecb4b306dc8b92a8f5e0f834764359d49cc6728b Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 15:53:55 +0800 Subject: [PATCH 07/12] refine rust check github action --- .github/workflows/pr-check-rust.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index a101de89..430d36aa 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -28,11 +28,6 @@ jobs: - name: Checkout PR uses: actions/checkout@v3 - - name: Set up Rust action - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - - name: Install dependencies run: | sudo apt update && yes | DEBIAN_FRONTEND=noninteractive sudo apt install -y libcryptsetup-dev clang protobuf-compiler protobuf-c-compiler libprotobuf-c-dev libprotobuf-c1 build-essential pkg-config libssl-dev From a760f1d053bccd44bf6bf5851e48b80a0421a38a Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 15:54:36 +0800 Subject: [PATCH 08/12] refine the action --- .github/workflows/pr-check-rust.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index 430d36aa..57da3b47 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -27,10 +27,11 @@ jobs: steps: - name: Checkout PR uses: actions/checkout@v3 - + - name: Install dependencies run: | sudo apt update && yes | DEBIAN_FRONTEND=noninteractive sudo apt install -y libcryptsetup-dev clang protobuf-compiler protobuf-c-compiler libprotobuf-c-dev libprotobuf-c1 build-essential pkg-config libssl-dev + - name: Run cargo check run: | cd common/rust/cctrusted_base/src From 4e151e65f66fd4df61578915aa2418ff92c65514 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 16:17:58 +0800 Subject: [PATCH 09/12] update runner --- .github/workflows/pr-check-rust.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index 57da3b47..e00439a9 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -23,11 +23,16 @@ on: jobs: codescan: - runs-on: tdx-runner + runs-on: ubuntu-latest steps: - name: Checkout PR uses: actions/checkout@v3 + - name: Set up Rust action + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.70.0 + - name: Install dependencies run: | sudo apt update && yes | DEBIAN_FRONTEND=noninteractive sudo apt install -y libcryptsetup-dev clang protobuf-compiler protobuf-c-compiler libprotobuf-c-dev libprotobuf-c1 build-essential pkg-config libssl-dev @@ -35,14 +40,12 @@ jobs: - name: Run cargo check run: | cd common/rust/cctrusted_base/src - cargo test cargo check cargo fmt -- --check cargo clippy cargo install --locked cargo-deny cargo deny check cd vmsdk/rust/cctrusted_vm/src/ - cargo test cargo check cargo fmt -- --check cargo clippy From f368eadd769b8273be914f5ddc57ab73841bab59 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 16:20:42 +0800 Subject: [PATCH 10/12] update code format according to rust code scan report --- common/rust/cctrusted_base/Cargo.toml | 1 - common/rust/cctrusted_base/src/api.rs | 2 +- common/rust/cctrusted_base/src/binary_blob.rs | 2 +- common/rust/cctrusted_base/src/tdx/quote.rs | 2 +- common/rust/cctrusted_base/src/tdx/rtmr.rs | 2 +- vmsdk/rust/cctrusted_vm/src/cvm.rs | 2 +- vmsdk/rust/cctrusted_vm/src/sdk.rs | 2 +- vmsdk/rust/cctrusted_vm/src/tdvm.rs | 2 +- vmsdk/rust/sample/src/cc-sample.rs | 2 +- 9 files changed, 8 insertions(+), 9 deletions(-) diff --git a/common/rust/cctrusted_base/Cargo.toml b/common/rust/cctrusted_base/Cargo.toml index 51cf0d5a..21509f3c 100644 --- a/common/rust/cctrusted_base/Cargo.toml +++ b/common/rust/cctrusted_base/Cargo.toml @@ -15,4 +15,3 @@ log = "0.4.20" sha2 = "0.10" lazy_static = "1.4.0" hashbrown = "0.14" - diff --git a/common/rust/cctrusted_base/src/api.rs b/common/rust/cctrusted_base/src/api.rs index 507e7c08..dfe84d50 100644 --- a/common/rust/cctrusted_base/src/api.rs +++ b/common/rust/cctrusted_base/src/api.rs @@ -125,4 +125,4 @@ impl ParseCcReport for CcReport { fn parse_cc_report(_report: Vec) -> Result { todo!() } -} \ No newline at end of file +} diff --git a/common/rust/cctrusted_base/src/binary_blob.rs b/common/rust/cctrusted_base/src/binary_blob.rs index 31738abf..0362a72e 100644 --- a/common/rust/cctrusted_base/src/binary_blob.rs +++ b/common/rust/cctrusted_base/src/binary_blob.rs @@ -56,4 +56,4 @@ pub fn dump_data(data: &Vec) { } else if index == data.len() { info!("{} {}", linestr, printstr); } -} \ No newline at end of file +} diff --git a/common/rust/cctrusted_base/src/tdx/quote.rs b/common/rust/cctrusted_base/src/tdx/quote.rs index 40edd4f1..9f81fc3d 100644 --- a/common/rust/cctrusted_base/src/tdx/quote.rs +++ b/common/rust/cctrusted_base/src/tdx/quote.rs @@ -92,4 +92,4 @@ impl TdxQuote { dummy_var2: 2, }) } -} \ No newline at end of file +} diff --git a/common/rust/cctrusted_base/src/tdx/rtmr.rs b/common/rust/cctrusted_base/src/tdx/rtmr.rs index 3c9a0134..ffb5d918 100644 --- a/common/rust/cctrusted_base/src/tdx/rtmr.rs +++ b/common/rust/cctrusted_base/src/tdx/rtmr.rs @@ -23,4 +23,4 @@ impl TcgIMR for TdxRTMR { fn is_valid(&self) -> bool { todo!() } -} \ No newline at end of file +} diff --git a/vmsdk/rust/cctrusted_vm/src/cvm.rs b/vmsdk/rust/cctrusted_vm/src/cvm.rs index 975ef031..120f6500 100644 --- a/vmsdk/rust/cctrusted_vm/src/cvm.rs +++ b/vmsdk/rust/cctrusted_vm/src/cvm.rs @@ -97,4 +97,4 @@ pub fn get_cvm_type() -> CcType { tee_type: tee_type.clone(), tee_type_str: TEE_NAME_MAP.get(&tee_type).unwrap().to_owned(), } -} \ No newline at end of file +} diff --git a/vmsdk/rust/cctrusted_vm/src/sdk.rs b/vmsdk/rust/cctrusted_vm/src/sdk.rs index ae034b1c..7a0692a5 100644 --- a/vmsdk/rust/cctrusted_vm/src/sdk.rs +++ b/vmsdk/rust/cctrusted_vm/src/sdk.rs @@ -69,4 +69,4 @@ impl CCTrustedApi for API { )), } } -} \ No newline at end of file +} diff --git a/vmsdk/rust/cctrusted_vm/src/tdvm.rs b/vmsdk/rust/cctrusted_vm/src/tdvm.rs index fd136b7d..3cdfef42 100644 --- a/vmsdk/rust/cctrusted_vm/src/tdvm.rs +++ b/vmsdk/rust/cctrusted_vm/src/tdvm.rs @@ -349,4 +349,4 @@ impl TcgAlgorithmRegistry for TdxVM { } } -impl BuildCVM for TdxVM {} \ No newline at end of file +impl BuildCVM for TdxVM {} diff --git a/vmsdk/rust/sample/src/cc-sample.rs b/vmsdk/rust/sample/src/cc-sample.rs index 38c39403..a1812153 100644 --- a/vmsdk/rust/sample/src/cc-sample.rs +++ b/vmsdk/rust/sample/src/cc-sample.rs @@ -29,4 +29,4 @@ fn main() { // dump the cc report with API "dump_cc_report" info!("call cc trusted API [dump_cc_report] to dump cc report!"); API::dump_cc_report(&report.cc_report); -} \ No newline at end of file +} From b9accb615fb26fb9dca4fe913e17fd9e7560a048 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 16:26:54 +0800 Subject: [PATCH 11/12] update cargo base work dir --- .github/workflows/pr-check-rust.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index e00439a9..7168ba03 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -39,13 +39,13 @@ jobs: - name: Run cargo check run: | - cd common/rust/cctrusted_base/src + cd common/rust/cctrusted_base/ cargo check cargo fmt -- --check cargo clippy cargo install --locked cargo-deny cargo deny check - cd vmsdk/rust/cctrusted_vm/src/ + cd vmsdk/rust/cctrusted_vm/ cargo check cargo fmt -- --check cargo clippy From 3f3fc3c1ce754952ed61e3aebd0689e2f38a2be5 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Thu, 11 Jan 2024 16:33:32 +0800 Subject: [PATCH 12/12] add check for VM SDK --- .github/workflows/pr-check-rust.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check-rust.yaml b/.github/workflows/pr-check-rust.yaml index 7168ba03..76107628 100644 --- a/.github/workflows/pr-check-rust.yaml +++ b/.github/workflows/pr-check-rust.yaml @@ -37,7 +37,7 @@ jobs: run: | sudo apt update && yes | DEBIAN_FRONTEND=noninteractive sudo apt install -y libcryptsetup-dev clang protobuf-compiler protobuf-c-compiler libprotobuf-c-dev libprotobuf-c1 build-essential pkg-config libssl-dev - - name: Run cargo check + - name: Run cargo check for cctrusted_base run: | cd common/rust/cctrusted_base/ cargo check @@ -45,6 +45,9 @@ jobs: cargo clippy cargo install --locked cargo-deny cargo deny check + + - name: Run cargo check for VM SDK + run: | cd vmsdk/rust/cctrusted_vm/ cargo check cargo fmt -- --check