blob: 8bff4e573791fc0229abcb08ff765e136111f731 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License..
#![allow(non_snake_case)]
extern crate itertools;
extern crate libloading;
extern crate sgx_types;
extern crate sgx_urts;
use itertools::*;
use sgx_types::*;
use sgx_urts::SgxEnclave;
static ENCLAVE_FILE: &'static str = "enclave.signed.so";
extern "C" {
fn enclave_create_report(
eid: sgx_enclave_id_t,
retval: *mut i32,
p_qe3_target: &sgx_target_info_t,
p_report: *mut sgx_report_t,
) -> sgx_status_t;
}
fn init_enclave() -> SgxResult<SgxEnclave> {
let mut launch_token: sgx_launch_token_t = [0; 1024];
let mut launch_token_updated: i32 = 0;
// call sgx_create_enclave to initialize an enclave instance
// Debug Support: set 2nd parameter to 1
let debug = 0;
let mut misc_attr = sgx_misc_attribute_t {
secs_attr: sgx_attributes_t { flags: 0, xfrm: 0 },
misc_select: 0,
};
SgxEnclave::create(
ENCLAVE_FILE,
debug,
&mut launch_token,
&mut launch_token_updated,
&mut misc_attr,
)
}
fn main() {
// quote holds the generated quote
let quote: Vec<u8> = generate_quote().unwrap();
// this quote has type `sgx_quote3_t` and is structured as:
// sgx_quote3_t {
// header: sgx_quote_header_t,
// report_body: sgx_report_body_t,
// signature_data_len: uint32_t, // 1116
// signature_data { // 1116 bytes payload
// sig_data: sgx_ql_ecdsa_sig_data_t { // 576 = 64x3 +384 header
// sig: [uint8_t; 64],
// attest_pub_key: [uint8_t; 64],
// qe3_report: sgx_report_body_t, // 384
// qe3_report_sig: [uint8_t; 64],
// auth_certification_data { // 2 + 32 = 34
// sgx_ql_auth_data_t: u16 // observed 32, size of following auth_data
// auth_data: [u8; sgx_ql_auth_data_t]
// }
// sgx_ql_certification_data_t {/ 2 + 4 + 500
// cert_key_type: uint16_t,
// size: uint32_t, // observed 500, size of following certificateion_data
// certification_data { // 500 bytes
// }
// }
// }
// }
// }
let p_quote3: *const sgx_quote3_t = quote.as_ptr() as *const sgx_quote3_t;
// copy heading bytes to a sgx_quote3_t type to simplify access
let quote3: sgx_quote3_t = unsafe { *p_quote3 };
let quote_signature_data_vec: Vec<u8> = quote[std::mem::size_of::<sgx_quote3_t>()..].into();
//println!("quote3 header says signature data len = {}", quote3.signature_data_len);
//println!("quote_signature_data len = {}", quote_signature_data_vec.len());
assert_eq!(
quote3.signature_data_len as usize,
quote_signature_data_vec.len()
);
// signature_data has a header of sgx_ql_ecdsa_sig_data_t structure
//let p_sig_data: * const sgx_ql_ecdsa_sig_data_t = quote_signature_data_vec.as_ptr() as _;
// mem copy
//let sig_data = unsafe { * p_sig_data };
// sgx_ql_ecdsa_sig_data_t is followed by sgx_ql_auth_data_t
// create a new vec for auth_data
let auth_certification_data_offset = std::mem::size_of::<sgx_ql_ecdsa_sig_data_t>();
let p_auth_data: *const sgx_ql_auth_data_t =
(quote_signature_data_vec[auth_certification_data_offset..]).as_ptr() as _;
let auth_data_header: sgx_ql_auth_data_t = unsafe { *p_auth_data };
//println!("auth_data len = {}", auth_data_header.size);
let auth_data_offset =
auth_certification_data_offset + std::mem::size_of::<sgx_ql_auth_data_t>();
// It should be [0,1,2,3...]
// defined at https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/4605fae1c606de4ff1191719433f77f050f1c33c/QuoteGeneration/quote_wrapper/quote/qe_logic.cpp#L1452
//let auth_data_vec: Vec<u8> = quote_signature_data_vec[auth_data_offset..auth_data_offset + auth_data_header.size as usize].into();
//println!("Auth data:\n{:?}", auth_data_vec);
let temp_cert_data_offset = auth_data_offset + auth_data_header.size as usize;
let p_temp_cert_data: *const sgx_ql_certification_data_t =
quote_signature_data_vec[temp_cert_data_offset..].as_ptr() as _;
let temp_cert_data: sgx_ql_certification_data_t = unsafe { *p_temp_cert_data };
//println!("certification data offset = {}", temp_cert_data_offset);
//println!("certification data size = {}", temp_cert_data.size);
let cert_info_offset =
temp_cert_data_offset + std::mem::size_of::<sgx_ql_certification_data_t>();
//println!("cert info offset = {}", cert_info_offset);
// this should be the last structure
assert_eq!(
quote_signature_data_vec.len(),
cert_info_offset + temp_cert_data.size as usize
);
let tail_content = quote_signature_data_vec[cert_info_offset..].to_vec();
let enc_ppid_len = 384;
let enc_ppid: &[u8] = &tail_content[0..enc_ppid_len];
let pce_id: &[u8] = &tail_content[enc_ppid_len..enc_ppid_len + 2];
let cpu_svn: &[u8] = &tail_content[enc_ppid_len + 2..enc_ppid_len + 2 + 16];
let pce_isvsvn: &[u8] = &tail_content[enc_ppid_len + 2 + 16..enc_ppid_len + 2 + 18];
println!("EncPPID:\n{:02x}", enc_ppid.iter().format(""));
println!("PCE_ID:\n{:02x}", pce_id.iter().format(""));
println!("TCBr - CPUSVN:\n{:02x}", cpu_svn.iter().format(""));
println!("TCBr - PCE_ISVSVN:\n{:02x}", pce_isvsvn.iter().format(""));
println!("QE_ID:\n{:02x}", quote3.header.user_data.iter().format(""));
}
// Re-invent App/utility.cpp
// int generate_quote(uint8_t **quote_buffer, uint32_t& quote_size)
fn generate_quote() -> Option<Vec<u8>> {
let mut ti: sgx_target_info_t = sgx_target_info_t::default();
let _l = libloading::Library::new("./libdcap_quoteprov.so.1").unwrap();
println!("Step1: Call sgx_qe_get_target_info:");
//println!("sgx_qe_get_target_info = {:p}", sgx_qe_get_target_info as * const _);
let qe3_ret = unsafe { sgx_qe_get_target_info(&mut ti as *mut _) };
if qe3_ret != sgx_quote3_error_t::SGX_QL_SUCCESS {
println!("Error in sgx_qe_get_target_info. {:?}\n", qe3_ret);
return None;
}
//println!("target_info.mr_enclave = {:?}", ti.mr_enclave.m);
//println!("target_info.config_id = {:02x}", ti.config_id.iter().format(" "));
let quote_size = std::mem::size_of::<sgx_target_info_t>();
let mut v: Vec<u8> = vec![0; quote_size];
unsafe {
std::ptr::copy_nonoverlapping(
&ti as *const sgx_target_info_t as *const u8,
v.as_mut_ptr() as *mut u8,
quote_size,
);
}
//println!("quote = {:?}", v);
println!("succeed!\nStep2: Call create_app_report:");
let app_report: sgx_report_t = if let Some(r) = create_app_enclave_report(&ti) {
println!("succeed! \nStep3: Call sgx_qe_get_quote_size:");
r
} else {
println!("\nCall to create_app_report() failed\n");
return None;
};
//println!("app_report.body.cpu_svn = {:02x}", app_report.body.cpu_svn.svn.iter().format(""));
//println!("app_report.body.misc_select = {:08x}", app_report.body.misc_select);
//println!("app_report.key_id = {:02x}", app_report.key_id.id.iter().format(""));
//println!("app_report.mac = {:02x}", app_report.mac.iter().format(""));
let mut quote_size: u32 = 0;
let qe3_ret = unsafe { sgx_qe_get_quote_size(&mut quote_size as _) };
if qe3_ret != sgx_quote3_error_t::SGX_QL_SUCCESS {
println!("Error in sgx_qe_get_quote_size . {:?}\n", qe3_ret);
return None;
}
println!("succeed!");
let mut quote_vec: Vec<u8> = vec![0; quote_size as usize];
println!("\nStep4: Call sgx_qe_get_quote:");
let qe3_ret =
unsafe { sgx_qe_get_quote(&app_report as _, quote_size, quote_vec.as_mut_ptr() as _) };
if qe3_ret != sgx_quote3_error_t::SGX_QL_SUCCESS {
println!("Error in sgx_qe_get_quote. {:?}\n", qe3_ret);
return None;
}
Some(quote_vec)
}
fn create_app_enclave_report(qe_ti: &sgx_target_info_t) -> Option<sgx_report_t> {
let enclave = if let Ok(r) = init_enclave() {
r
} else {
return None;
};
let mut retval = 0;
let mut ret_report: sgx_report_t = sgx_report_t::default();
let result = unsafe {
enclave_create_report(
enclave.geteid(),
&mut retval,
qe_ti,
&mut ret_report as *mut sgx_report_t,
)
};
match result {
sgx_status_t::SGX_SUCCESS => {}
_ => {
println!("[-] ECALL Enclave Failed {}!", result.as_str());
return None;
}
}
enclave.destroy();
Some(ret_report)
}