diff --git a/remote-attestation/Cargo.toml b/remote-attestation/Cargo.toml index 8c89c93..d7b13f3 100644 --- a/remote-attestation/Cargo.toml +++ b/remote-attestation/Cargo.toml @@ -7,12 +7,15 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +sgx_types = "1.1.1" +sgx_tse = "1.1.1" +sgx_tstd = { rev = "v1.1.2", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["net"] } anyhow = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/anyhow-sgx.git" } webpki = { branch = "mesalock_sgx", git = "https://github.com/mesalock-linux/webpki" } # Specify branch name due to rustls dependency -sgx_tstd = { rev = "v1.1.2", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["net"] } http_req = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/http_req-sgx" } serde_json = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/serde-json-sgx" } serde = { git = "https://github.com/mesalock-linux/serde-sgx.git" } # Don't specify version due to serde_json dependency base64 = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/rust-base64-sgx" } rustls = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/rustls" } log = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/log-sgx" } +hex = { rev = "sgx_1.1.2", git = "https://github.com/mesalock-linux/rust-hex-sgx" } diff --git a/remote-attestation/src/client.rs b/remote-attestation/src/client.rs index 292c72e..2e40d67 100644 --- a/remote-attestation/src/client.rs +++ b/remote-attestation/src/client.rs @@ -1,19 +1,14 @@ use std::{ prelude::v1::*, - net::TcpStream, - str, time::{SystemTime, UNIX_EPOCH}, - untrusted::time::SystemTimeEx, io::{BufReader, Write}, - collections::HashMap, }; use http_req::{request::{Request, Method}, uri::Uri, response::{Headers, Response}}; use anyhow::{Result, anyhow, bail, ensure}; use serde_json::Value; use log::debug; - -pub const TEST_SUB_KEY: &str = "77e2533de0624df28dc3be3a5b9e50d9"; -pub const TEST_SPID: &str = "2C149BFC94A61D306A96211AED155BE9"; +use sgx_types::{sgx_report_data_t, sgx_spid_t}; +use crate::quote::{sgx_init_quote, get_quote}; pub const IAS_REPORT_CA: &[u8] = include_bytes!("../AttestationReportSigningCACert.pem"); type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; @@ -32,16 +27,41 @@ static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ ]; /// The very high level service for remote attestations -pub struct RAService; +pub struct RAService { + encoded_quote: String, +} impl RAService { + // spid: Service provider ID for the ISV. + /// Generate Base64-encoded QUOTE data structure. + /// QUOTE will be sent to Attestation Service to verify SGX's status. + /// For more information: https://api.trustedservices.intel.com/documents/sgx-attestation-api-spec.pdf + pub fn new(spid: &str, report_data: &sgx_report_data_t) -> Result { + let spid_vec = hex::decode(spid)?; + let mut id = [0; 16]; + id.copy_from_slice(&spid_vec); + let spid: sgx_spid_t = sgx_spid_t { id }; + + let target_info = sgx_init_quote()?; + let report = sgx_tse::rsgx_create_report(&target_info, &report_data) + .map_err(|e| anyhow!("{}", e))?; + let quote = get_quote(report, &spid)?; + + // Use base64-encoded QUOTE structure to communicate via defined API. + let encoded_quote = base64::encode("e); + + Ok(RAService { + encoded_quote, + }) + } + pub fn remote_attestation( + &self, uri: &str, ias_api_key: &str, - quote: &str, ) -> Result<(AttestationReport, ReportSig)> { let uri: Uri = uri.parse().expect("Invalid uri"); - let body = format!("{{\"isvEnclaveQuote\":\"{}\"}}\r\n", quote); + let body = format!("{{\"isvEnclaveQuote\":\"{}\"}}\r\n", &self.encoded_quote); let mut writer = Vec::new(); let response = RAClient::new(&uri) diff --git a/remote-attestation/src/lib.rs b/remote-attestation/src/lib.rs index e14bd6a..2e7c6dd 100644 --- a/remote-attestation/src/lib.rs +++ b/remote-attestation/src/lib.rs @@ -4,5 +4,6 @@ extern crate sgx_tstd as std; mod client; +mod quote; pub use crate::client::{RAService, AttestationReport, ReportSig}; diff --git a/remote-attestation/src/quote.rs b/remote-attestation/src/quote.rs new file mode 100644 index 0000000..2fb90a2 --- /dev/null +++ b/remote-attestation/src/quote.rs @@ -0,0 +1,74 @@ +use sgx_types::*; +use anyhow::{Result, ensure}; +use std::vec::Vec; + +extern "C" { + pub fn ocall_sgx_init_quote( + retval: *mut sgx_status_t, + ret_ti: *mut sgx_target_info_t, + ret_gid: *mut sgx_epid_group_id_t, + ) -> sgx_status_t; +} +extern "C" { + pub fn ocall_get_quote( + retval: *mut sgx_status_t, + p_sigrl: *const u8, + sigrl_len: u32, + report: *const sgx_report_t, + quote_type: sgx_quote_sign_type_t, + p_spid: *const sgx_spid_t, + p_nonce: *const sgx_quote_nonce_t, + p_qe_report: *mut sgx_report_t, + p_quote: *mut sgx_quote_t, + maxlen: u32, + p_quote_len: *mut u32, + ) -> sgx_status_t; +} + +pub fn sgx_init_quote() -> Result { + let mut rt = sgx_status_t::SGX_ERROR_UNEXPECTED; + let mut target_info = sgx_target_info_t::default(); + let mut gid = sgx_epid_group_id_t::default(); + + let status = unsafe { + ocall_sgx_init_quote( + &mut rt as *mut sgx_status_t, + &mut target_info as *mut sgx_target_info_t, + &mut gid as *mut sgx_epid_group_id_t, + ) + }; + + ensure!(status == sgx_status_t::SGX_SUCCESS, "Ocall Error ocall_sgx_init_quote: {:?}", status); + ensure!(rt == sgx_status_t::SGX_SUCCESS, "Init Quote Error: {:?}", status); + + Ok(target_info) +} + +pub fn get_quote(report: sgx_report_t, spid: &sgx_spid_t) -> Result> { + const RET_QUOTE_BUF_LEN : u32 = 2048; + let mut quote_len: u32 = 0; + let mut rt = sgx_status_t::SGX_ERROR_UNEXPECTED; + let mut quote = vec![0u8; RET_QUOTE_BUF_LEN as usize]; + + let status = unsafe { + ocall_get_quote( + &mut rt as *mut sgx_status_t, + std::ptr::null(), // p_sigrl + 0, // sigrl_len + &report as *const sgx_report_t, + sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE, // quote_type + spid as *const sgx_spid_t, // p_spid + std::ptr::null(), // p_nonce + std::ptr::null_mut(), // p_qe_report + quote.as_mut_ptr() as *mut sgx_quote_t, + RET_QUOTE_BUF_LEN, // maxlen + &mut quote_len as *mut u32, + ) + }; + + ensure!(status == sgx_status_t::SGX_SUCCESS, "Ocall Error ocall_get_quote: {:?}", status); + ensure!(rt == sgx_status_t::SGX_SUCCESS, "Get Quote Error: {:?}", status); + + let _ = quote.split_off(quote_len as usize); + Ok(quote) +}