From f6ae5be0b04f195fbbb057408a8bf3a6788427b3 Mon Sep 17 00:00:00 2001 From: hairongchen Date: Fri, 1 Mar 2024 14:34:01 +0800 Subject: [PATCH 1/2] Rust SDK: enhance to support get TDX quote via vsock Signed-off-by: Hairong Chen hairong.chen@intel.com --- src/rust/cctrusted_vm/Cargo.toml | 3 + src/rust/cctrusted_vm/src/sdk.rs | 2 +- src/rust/cctrusted_vm/src/tdvm.rs | 160 ++++++++++++++++++++++--- src/rust/sample/Cargo.toml | 4 +- src/rust/sample/src/cc-sample-quote.rs | 6 +- 5 files changed, 154 insertions(+), 21 deletions(-) diff --git a/src/rust/cctrusted_vm/Cargo.toml b/src/rust/cctrusted_vm/Cargo.toml index 9a1ea74..d67b8b3 100644 --- a/src/rust/cctrusted_vm/Cargo.toml +++ b/src/rust/cctrusted_vm/Cargo.toml @@ -18,3 +18,6 @@ log = "0.4.20" nix = "0.26.2" base64 = "0.13.0" rand = "0.8.5" +vsock = "0.4.0" +tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +tokio-stream = "0.1.14" \ No newline at end of file diff --git a/src/rust/cctrusted_vm/src/sdk.rs b/src/rust/cctrusted_vm/src/sdk.rs index 1969273..12360c3 100644 --- a/src/rust/cctrusted_vm/src/sdk.rs +++ b/src/rust/cctrusted_vm/src/sdk.rs @@ -21,7 +21,7 @@ impl CCTrustedApi for API { match build_cvm() { Ok(mut cvm) => { // call CVM trait defined methods - cvm.dump(); + // cvm.dump(); Ok(CcReport { cc_report: match cvm.process_cc_report(nonce, data) { Ok(r) => r, diff --git a/src/rust/cctrusted_vm/src/tdvm.rs b/src/rust/cctrusted_vm/src/tdvm.rs index 07dd061..7434fbf 100644 --- a/src/rust/cctrusted_vm/src/tdvm.rs +++ b/src/rust/cctrusted_vm/src/tdvm.rs @@ -5,25 +5,21 @@ use anyhow::*; use cctrusted_base::api_data::ReplayResult; use cctrusted_base::cc_type::*; use cctrusted_base::eventlog::EventLogs; -use cctrusted_base::tcg::EventLogEntry; use cctrusted_base::tcg::*; -use cctrusted_base::tdx::common::*; -use cctrusted_base::tdx::quote::*; -use cctrusted_base::tdx::report::*; -use cctrusted_base::tdx::rtmr::TdxRTMR; +use cctrusted_base::tdx::{common::*, quote::*, report::*, rtmr::TdxRTMR}; use core::convert::TryInto; -use core::mem; +use core::mem::*; use core::ptr; use core::result::Result; use core::result::Result::Ok; use log::info; +use nix::sys::socket::*; use nix::*; -use std::fs::read_to_string; -use std::fs::File; -use std::io::BufReader; -use std::io::Read; +use std::fs::{read_to_string, File}; +use std::io::{BufReader, Read}; use std::os::fd::AsRawFd; use std::path::Path; +use vsock::VMADDR_CID_HOST; // TDX ioctl operation code to be used for get TDX quote and TD Report pub enum TdxOperation { @@ -222,20 +218,152 @@ impl CVM for TdxVM { //build QGS request message let qgs_msg = Tdx::generate_qgs_quote_msg(report_data_array); + 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, size_of::()) + }; + + // use TDVMCALL by default except vsock config exists at ATTEST_CFG_FILE_PATH + let mut tdvmcall_flag = true; + let mut port: u32 = 0; + if Path::new(ATTEST_CFG_FILE_PATH).exists() { + let data_lines: Vec = read_to_string(ATTEST_CFG_FILE_PATH) + .unwrap() + .lines() + .map(String::from) + .collect(); + + for line in data_lines { + if line.contains("port") { + let element = line + .split('=') + .last() + .expect("[process_cc_report] invalid vsock port config") + .trim_matches(' '); + port = element.parse().unwrap(); + if port >= 65536 { + return Err(anyhow!( + "[process_cc_report] invalid vsock port config at {}", + ATTEST_CFG_FILE_PATH + )); + } + tdvmcall_flag = false; + break; + } + } + } + + // get quote using vsock instead of TDVMCALL + if !tdvmcall_flag { + log::info!("[process_cc_report] get TDX quote with vsock"); + const HEADER_SIZE: u32 = 4; + const QUOTE_BUFFER_SIZE: usize = 10000; + let qgs_msg_bytes_array: [u8; (16 + 8 + TDX_REPORT_LEN) as usize] = + unsafe { transmute(qgs_msg) }; + let msg_size: u32 = qgs_msg_bytes_array.len().try_into().unwrap(); + let msg_size_bytes_array: [u8; HEADER_SIZE as usize] = msg_size.to_be().to_ne_bytes(); + + let mut p_blob_payload = [0; (HEADER_SIZE + 16 + 8 + TDX_REPORT_LEN) as usize]; + p_blob_payload[..4].copy_from_slice(&msg_size_bytes_array); + p_blob_payload[4..].copy_from_slice(&qgs_msg_bytes_array); + + let vsock_addr = VsockAddr::new(VMADDR_CID_HOST, port); + let qgs_vsocket = socket( + AddressFamily::Vsock, + SockType::Stream, + SockFlag::empty(), + None, + ) + .context("[get_td_report] failed to create vsock socket")?; + + let _ = connect(qgs_vsocket.as_raw_fd(), &vsock_addr) + .with_context(|| "[get_td_report] failed to connect to qgs vsock".to_string()); + + match send(qgs_vsocket.as_raw_fd(), &p_blob_payload, MsgFlags::empty()) { + Ok(written_bytes) => { + if written_bytes != p_blob_payload.len() { + return Err(anyhow!( + "[process_cc_report] send to qgs vsock failed: send {} bytes", + written_bytes + )); + } + } + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to send to qgs vsock: {:?}", + e + )) + } + } + + let mut return_size_bytes_array = [0; HEADER_SIZE as usize]; + match recv( + qgs_vsocket.as_raw_fd(), + &mut return_size_bytes_array, + MsgFlags::empty(), + ) { + Ok(read_bytes) => { + if read_bytes != HEADER_SIZE.try_into().unwrap() { + return Err(anyhow!("[process_cc_report] read size header from qgs vsock failed: read {} bytes", read_bytes)); + } + } + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to read size header from qgs vsock: {:?}", + e + )) + } + } + + let mut in_msg_size = 0; + for i in 0..HEADER_SIZE { + in_msg_size = (in_msg_size << 8) + (return_size_bytes_array[i as usize]) as u32; + } + + let mut return_quote_bytes_array = [0; QUOTE_BUFFER_SIZE]; + match recv( + qgs_vsocket.as_raw_fd(), + &mut return_quote_bytes_array, + MsgFlags::empty(), + ) { + Ok(read_qgs_response_bytes) => { + if read_qgs_response_bytes == 0 { + return Err(anyhow!( + "[process_cc_report] read quote body from qgs vsock failed: got 0 byte" + )); + } + } + Err(e) => { + return Err(anyhow!( + "[get_td_report] Fail to read quote body from qgs vsock: {:?}", + e + )) + } + } + + let qgs_msg_resp = unsafe { + let raw_ptr = + ptr::addr_of!(return_quote_bytes_array) as *mut qgs_msg_get_quote_resp; + raw_ptr.as_mut().unwrap() as &mut qgs_msg_get_quote_resp + }; + + let _ = shutdown(qgs_vsocket.as_raw_fd(), Shutdown::Both); + + return Ok(qgs_msg_resp.id_quote[0..(qgs_msg_resp.quote_size as usize)].to_vec()); + } + + log::info!("[process_cc_report] get TDX quote with TDVMCALL"); + //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, + in_len: (size_of_val(&qgs_msg) + 4) as u32, out_len: 0, data_len_be_bytes: (1048_u32).to_be_bytes(), data: [0; TDX_QUOTE_LEN], }; - 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)]); @@ -304,7 +432,7 @@ impl CVM for TdxVM { //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(); + unsafe { 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; diff --git a/src/rust/sample/Cargo.toml b/src/rust/sample/Cargo.toml index 706a88d..473b72a 100644 --- a/src/rust/sample/Cargo.toml +++ b/src/rust/sample/Cargo.toml @@ -18,9 +18,9 @@ path = "src/cc-sample-eventlog.rs" [dependencies] cctrusted_vm = { path = "../cctrusted_vm" } -cctrusted_base = { git = "https://github.com/cc-api/cc-trusted-api.git", branch = "main" } +cctrusted_base = { path = "../../../common/rust/cctrusted_base" } anyhow = "1.0" log = "0.4.20" env_logger = "0.10.1" base64 = "0.13.0" -rand = "0.8.5" +rand = "0.8.5" \ No newline at end of file diff --git a/src/rust/sample/src/cc-sample-quote.rs b/src/rust/sample/src/cc-sample-quote.rs index 622c697..472f4bf 100644 --- a/src/rust/sample/src/cc-sample-quote.rs +++ b/src/rust/sample/src/cc-sample-quote.rs @@ -29,9 +29,11 @@ fn main() { } }; + info!("cc report size {}", report.cc_report.len()); + // 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); + // 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 { From d0fd1fcd9cdc0fa2a86d13435eb461a78fe46bca Mon Sep 17 00:00:00 2001 From: hairongchen Date: Fri, 1 Mar 2024 14:37:04 +0800 Subject: [PATCH 2/2] update crate location of trused_base --- src/rust/sample/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/sample/Cargo.toml b/src/rust/sample/Cargo.toml index 473b72a..f1bbede 100644 --- a/src/rust/sample/Cargo.toml +++ b/src/rust/sample/Cargo.toml @@ -18,7 +18,7 @@ path = "src/cc-sample-eventlog.rs" [dependencies] cctrusted_vm = { path = "../cctrusted_vm" } -cctrusted_base = { path = "../../../common/rust/cctrusted_base" } +cctrusted_base = { git = "https://github.com/cc-api/cc-trusted-api.git", branch = "main" } anyhow = "1.0" log = "0.4.20" env_logger = "0.10.1"