use sgx_types::*;
use sgx_types::marker::ContiguousMemory;
use sgx_trts::trts::*;
use sgx_trts::memeq::ConsttimeMemEq;
use sgx_tcrypto::*;
use sgx_tse::*;
use ecp::*;
use core::mem;
use core::ptr;
use alloc::slice;
use alloc::vec::Vec;
use alloc::boxed::Box;
const AES_CMAC_KDF_ID: [u8; 2] = [1, 0];
pub type SgxDhMsg1 = sgx_dh_msg1_t;
pub type SgxDhMsg2 = sgx_dh_msg2_t;
#[derive(Clone, Default)]
pub struct SgxDhMsg3Body {
pub report: sgx_report_t,
pub additional_prop: Box<[u8]>,
}
#[derive(Clone, Default)]
pub struct SgxDhMsg3 {
pub cmac: [u8; SGX_DH_MAC_SIZE],
pub msg3_body: SgxDhMsg3Body,
}
impl SgxDhMsg3 {
pub fn new() -> Self {
SgxDhMsg3::default()
}
pub fn calc_raw_sealed_data_size(&self) -> u32 {
let max = u32::max_value();
let dh_msg3_size = mem::size_of::<sgx_dh_msg3_t>();
let additional_prop_len = self.msg3_body.additional_prop.len();
if additional_prop_len > (max as usize) - dh_msg3_size {
return max;
}
(dh_msg3_size + additional_prop_len) as u32
}
pub unsafe fn to_raw_dh_msg3_t(&self, p: * mut sgx_dh_msg3_t, len: u32) -> Option<* mut sgx_dh_msg3_t> {
if p.is_null() {
return None;
}
if !rsgx_raw_is_within_enclave(p as * mut u8, len as usize) {
return None;
}
let additional_prop_len = self.msg3_body.additional_prop.len();
let dh_msg3_size = mem::size_of::<sgx_dh_msg3_t>();
if additional_prop_len > u32::max_value() as usize - dh_msg3_size {
return None;
}
if len < (dh_msg3_size + additional_prop_len) as u32 {
return None;
}
let dh_msg3 = &mut *p;
dh_msg3.cmac = self.cmac;
dh_msg3.msg3_body.report = self.msg3_body.report;
dh_msg3.msg3_body.additional_prop_length = additional_prop_len as u32;
if additional_prop_len > 0 {
let raw_msg3 = slice::from_raw_parts_mut(p as * mut u8, len as usize);
raw_msg3[dh_msg3_size..].copy_from_slice(&self.msg3_body.additional_prop);
}
Some(p)
}
pub unsafe fn from_raw_dh_msg3_t(p: * mut sgx_dh_msg3_t, len: u32) -> Option<Self> {
if p.is_null() {
return None;
}
if !rsgx_raw_is_within_enclave(p as * mut u8, len as usize) {
return None;
}
let raw_msg3 = &*p;
let additional_prop_len = raw_msg3.msg3_body.additional_prop_length;
let dh_msg3_size = mem::size_of::<sgx_dh_msg3_t>() as u32;
if additional_prop_len > u32::max_value() - dh_msg3_size {
return None;
}
if len < dh_msg3_size + additional_prop_len {
return None;
}
let mut dh_msg3 = SgxDhMsg3::default();
dh_msg3.cmac = raw_msg3.cmac;
dh_msg3.msg3_body.report = raw_msg3.msg3_body.report;
if additional_prop_len > 0 {
let mut additional_prop: Vec<u8> = vec![0_u8; additional_prop_len as usize];
let ptr_additional_prop = p.offset(1) as * const u8;
ptr::copy_nonoverlapping(ptr_additional_prop, additional_prop.as_mut_ptr(), additional_prop_len as usize);
dh_msg3.msg3_body.additional_prop = additional_prop.into_boxed_slice();
}
Some(dh_msg3)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
enum SgxDhSessionState {
SGX_DH_SESSION_STATE_ERROR,
SGX_DH_SESSION_STATE_RESET,
SGX_DH_SESSION_RESPONDER_WAIT_M2,
SGX_DH_SESSION_INITIATOR_WAIT_M1,
SGX_DH_SESSION_INITIATOR_WAIT_M3,
SGX_DH_SESSION_ACTIVE,
}
#[derive(Copy, Clone)]
pub struct SgxDhResponder {
state: SgxDhSessionState,
prv_key: sgx_ec256_private_t,
pub_key: sgx_ec256_public_t,
smk_aek: sgx_key_128bit_t,
shared_key: sgx_ec256_dh_shared_t,
}
impl Default for SgxDhResponder {
fn default() -> Self {
SgxDhResponder {
state: SgxDhSessionState::SGX_DH_SESSION_STATE_RESET,
prv_key: sgx_ec256_private_t::default(),
pub_key: sgx_ec256_public_t::default(),
smk_aek: sgx_key_128bit_t::default(),
shared_key: sgx_ec256_dh_shared_t::default(),
}
}
}
unsafe impl ContiguousMemory for SgxDhResponder {}
impl SgxDhResponder {
pub fn init_session() -> Self {
Self::default()
}
pub fn gen_msg1(&mut self, msg1: &mut SgxDhMsg1) -> SgxError {
if !rsgx_data_is_within_enclave(self) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if !rsgx_data_is_within_enclave(msg1) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if self.state != SgxDhSessionState::SGX_DH_SESSION_STATE_RESET {
*self = Self::default();
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let error = self.dh_generate_message1(msg1);
if let Err(mut ret) = error {
*self = Self::default();
if ret != sgx_status_t::SGX_ERROR_OUT_OF_MEMORY {
ret = sgx_status_t::SGX_ERROR_UNEXPECTED;
}
return Err(ret);
}
self.state = SgxDhSessionState::SGX_DH_SESSION_RESPONDER_WAIT_M2;
Ok(())
}
pub fn proc_msg2(&mut self,
msg2: &SgxDhMsg2,
msg3: &mut SgxDhMsg3,
aek: &mut sgx_key_128bit_t,
initiator_identity: &mut sgx_dh_session_enclave_identity_t) -> SgxError {
if !rsgx_data_is_within_enclave(self) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if !rsgx_data_is_within_enclave(msg2) ||
!rsgx_data_is_within_enclave(aek) ||
!rsgx_data_is_within_enclave(initiator_identity) ||
!rsgx_raw_is_within_enclave(msg3 as * const _ as * const u8, mem::size_of::<SgxDhMsg3>()) {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if msg3.msg3_body.additional_prop.len() > 0 &&
(!(rsgx_slice_is_within_enclave(&msg3.msg3_body.additional_prop)) ||
(msg3.msg3_body.additional_prop.len() > (u32::max_value() as usize) - mem::size_of::<sgx_dh_msg3_t>())) {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if self.state != SgxDhSessionState::SGX_DH_SESSION_RESPONDER_WAIT_M2 {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ecc_state = SgxEccHandle::new();
try!(ecc_state.open().map_err(|ret| self.set_error(ret)));
self.shared_key = try!(ecc_state.compute_shared_dhkey(&self.prv_key, &msg2.g_b).map_err(|ret| self.set_error(ret)));
self.smk_aek = try!(derive_key(&self.shared_key, &EC_SMK_LABEL).map_err(|ret| self.set_error(ret)));
#[cfg(feature = "use_lav2")]
try!(self.lav2_verify_message2(msg2).map_err(|ret| self.set_error(ret)));
#[cfg(not(feature = "use_lav2"))]
try!(self.dh_verify_message2(msg2).map_err(|ret| self.set_error(ret)));
initiator_identity.isv_svn = msg2.report.body.isv_svn;
initiator_identity.isv_prod_id = msg2.report.body.isv_prod_id;
initiator_identity.attributes = msg2.report.body.attributes;
initiator_identity.mr_signer = msg2.report.body.mr_signer;
initiator_identity.mr_enclave = msg2.report.body.mr_enclave;
#[cfg(feature = "use_lav2")]
try!(self.lav2_generate_message3(msg2, msg3).map_err(|ret| self.set_error(ret)));
#[cfg(not(feature = "use_lav2"))]
try!(self.dh_generate_message3(msg2, msg3).map_err(|ret| self.set_error(ret)));
* aek = try!(derive_key(&self.shared_key, &EC_AEK_LABEL).map_err(|ret| self.set_error(ret)));
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_ACTIVE;
Ok(())
}
fn dh_generate_message1(&mut self, msg1: &mut SgxDhMsg1) -> SgxError {
msg1.target = Default::default();
msg1.g_a = Default::default();
let mut target = sgx_target_info_t::default();
let report_data = sgx_report_data_t::default();
let report = try!(rsgx_create_report(&target, &report_data));
try!(SGX_LAV2_PROTO_SPEC.make_target_info(&report, &mut target));
let ecc_state = SgxEccHandle::new();
try!(ecc_state.open());
let (prv_key, pub_key) = try!(ecc_state.create_key_pair());
self.prv_key = prv_key;
self.pub_key = pub_key;
msg1.g_a = pub_key;
msg1.target = target;
Ok(())
}
fn dh_verify_message2(&self, msg2: &SgxDhMsg2) -> SgxError {
let kdf_id = &msg2.report.body.report_data.d[SGX_SHA256_HASH_SIZE..SGX_SHA256_HASH_SIZE + 2];
let data_hash = &msg2.report.body.report_data.d[..SGX_SHA256_HASH_SIZE];
if !kdf_id.eq(&AES_CMAC_KDF_ID) {
return Err(sgx_status_t::SGX_ERROR_KDF_MISMATCH);
}
let report = msg2.report;
let data_mac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &report));
if !data_mac.consttime_memeq(&msg2.cmac) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
try!(rsgx_verify_report(&report));
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&self.pub_key));
try!(sha_handle.update_msg(&msg2.g_b));
let msg_hash = try!(sha_handle.get_hash());
if !msg_hash.eq(data_hash) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
Ok(())
}
fn lav2_verify_message2(&self, msg2: &SgxDhMsg2) -> SgxError {
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&msg2.report.body.report_data));
try!(sha_handle.update_msg(&msg2.g_b));
let msg_hash = try!(sha_handle.get_hash());
let mut report = msg2.report;
report.body.report_data = sgx_report_data_t::default();
report.body.report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
try!(rsgx_verify_report(&report));
let data_mac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &msg2.g_b));
if !data_mac.consttime_memeq(&msg2.cmac) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
let proto_spec = unsafe { SgxLAv2ProtoSpec::from_report_data(&msg2.report.body.report_data) };
if (!proto_spec.signature.eq(&SGX_LAV2_PROTO_SPEC.signature)) || (proto_spec.ver != SGX_LAV2_PROTO_SPEC.ver) {
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
}
Ok(())
}
fn dh_generate_message3(&self, msg2: &SgxDhMsg2, msg3: &mut SgxDhMsg3) -> SgxError {
msg3.cmac = Default::default();
msg3.msg3_body.report = Default::default();
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&msg2.g_b));
try!(sha_handle.update_msg(&self.pub_key));
let msg_hash = try!(sha_handle.get_hash());
let mut target = sgx_target_info_t::default();
let mut report_data = sgx_report_data_t::default();
let report = msg2.report;
report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
try!(SGX_LAV2_PROTO_SPEC.make_target_info(&report, &mut target));
msg3.msg3_body.report = try!(rsgx_create_report(&target, &report_data));
let add_prop_len = msg3.msg3_body.additional_prop.len() as u32;
let cmac_handle = SgxCmacHandle::new();
try!(cmac_handle.init(&self.smk_aek));
try!(cmac_handle.update_msg(&msg3.msg3_body.report));
try!(cmac_handle.update_msg(&add_prop_len));
if add_prop_len > 0 {
try!(cmac_handle.update_slice(&msg3.msg3_body.additional_prop));
}
msg3.cmac = try!(cmac_handle.get_hash());
Ok(())
}
fn lav2_generate_message3(&self, msg2: &SgxDhMsg2, msg3: &mut SgxDhMsg3) -> SgxError {
msg3.cmac = Default::default();
msg3.msg3_body.report = Default::default();
let proto_spec = unsafe { SgxLAv2ProtoSpec::from_report_data(&msg2.report.body.report_data) };
let mut target = sgx_target_info_t::default();
let mut report_data = sgx_report_data_t::default();
let report = msg2.report;
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&self.pub_key));
try!(sha_handle.update_msg(&proto_spec));
let msg_hash = try!(sha_handle.get_hash());
report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
try!(SGX_LAV2_PROTO_SPEC.make_target_info(&report, &mut target));
msg3.msg3_body.report = try!(rsgx_create_report(&target, &report_data));
let cmac_handle = SgxCmacHandle::new();
try!(cmac_handle.init(&self.smk_aek));
if msg3.msg3_body.additional_prop.len() > 0 {
try!(cmac_handle.update_slice(&msg3.msg3_body.additional_prop));
}
try!(cmac_handle.update_msg(&self.pub_key));
msg3.cmac = try!(cmac_handle.get_hash());
Ok(())
}
fn set_error(&mut self, sgx_ret: sgx_status_t) -> sgx_status_t {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
match sgx_ret {
sgx_status_t::SGX_ERROR_OUT_OF_MEMORY => sgx_status_t::SGX_ERROR_OUT_OF_MEMORY,
sgx_status_t::SGX_ERROR_KDF_MISMATCH => sgx_status_t::SGX_ERROR_KDF_MISMATCH,
_ => sgx_status_t::SGX_ERROR_UNEXPECTED,
}
}
}
#[derive(Copy, Clone)]
pub struct SgxDhInitiator {
state: SgxDhSessionState,
smk_aek: sgx_key_128bit_t,
pub_key: sgx_ec256_public_t,
peer_pub_key: sgx_ec256_public_t,
shared_key: sgx_ec256_dh_shared_t,
}
impl Default for SgxDhInitiator {
fn default() -> Self {
SgxDhInitiator {
state: SgxDhSessionState::SGX_DH_SESSION_INITIATOR_WAIT_M1,
smk_aek: sgx_key_128bit_t::default(),
pub_key: sgx_ec256_public_t::default(),
peer_pub_key: sgx_ec256_public_t::default(),
shared_key: sgx_ec256_dh_shared_t::default(),
}
}
}
unsafe impl ContiguousMemory for SgxDhInitiator {}
impl SgxDhInitiator {
pub fn init_session() -> Self {
Self::default()
}
pub fn proc_msg1(&mut self, msg1: &SgxDhMsg1, msg2: &mut SgxDhMsg2) -> SgxError {
if !rsgx_data_is_within_enclave(self) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if !rsgx_data_is_within_enclave(msg1) ||
!rsgx_data_is_within_enclave(msg2) {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if self.state != SgxDhSessionState::SGX_DH_SESSION_INITIATOR_WAIT_M1 {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
let ecc_state = SgxEccHandle::new();
try!(ecc_state.open().map_err(|ret| self.set_error(ret)));
let (mut prv_key, pub_key) = try!(ecc_state.create_key_pair().map_err(|ret| self.set_error(ret)));
self.shared_key = try!(ecc_state.compute_shared_dhkey(&prv_key, &msg1.g_a).map_err(|ret| self.set_error(ret)));
prv_key = sgx_ec256_private_t::default();
self.pub_key = pub_key;
self.smk_aek = try!(derive_key(&self.shared_key, &EC_SMK_LABEL).map_err(|ret| self.set_error(ret)));
#[cfg(feature = "use_lav2")]
try!(self.lav2_generate_message2(msg1, msg2).map_err(|ret| self.set_error(ret)));
#[cfg(not(feature = "use_lav2"))]
try!(self.dh_generate_message2(msg1, msg2).map_err(|ret| self.set_error(ret)));
self.peer_pub_key = msg1.g_a;
self.state = SgxDhSessionState::SGX_DH_SESSION_INITIATOR_WAIT_M3;
Ok(())
}
pub fn proc_msg3(&mut self,
msg3: &SgxDhMsg3,
aek: &mut sgx_key_128bit_t,
responder_identity: &mut sgx_dh_session_enclave_identity_t) -> SgxError {
if !rsgx_data_is_within_enclave(self) {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if !rsgx_raw_is_within_enclave(msg3 as * const _ as * const u8, mem::size_of::<SgxDhMsg3>()) ||
!rsgx_data_is_within_enclave(aek) ||
!rsgx_data_is_within_enclave(responder_identity) {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if msg3.msg3_body.additional_prop.len() > 0 &&
(!rsgx_slice_is_within_enclave(&msg3.msg3_body.additional_prop) ||
(msg3.msg3_body.additional_prop.len() > (u32::max_value() as usize) - mem::size_of::<sgx_dh_msg3_t>())) {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
if self.state != SgxDhSessionState::SGX_DH_SESSION_INITIATOR_WAIT_M3 {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
return Err(sgx_status_t::SGX_ERROR_INVALID_STATE);
}
#[cfg(feature = "use_lav2")]
try!(self.lav2_verify_message3(msg3).map_err(|ret| self.set_error(ret)));
#[cfg(not(feature = "use_lav2"))]
try!(self.dh_verify_message3(msg3).map_err(|ret| self.set_error(ret)));
* aek = try!(derive_key(&self.shared_key, &EC_AEK_LABEL).map_err(|ret| self.set_error(ret)));
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_ACTIVE;
responder_identity.cpu_svn = msg3.msg3_body.report.body.cpu_svn;
responder_identity.misc_select = msg3.msg3_body.report.body.misc_select;
responder_identity.isv_svn = msg3.msg3_body.report.body.isv_svn;
responder_identity.isv_prod_id = msg3.msg3_body.report.body.isv_prod_id;
responder_identity.attributes = msg3.msg3_body.report.body.attributes;
responder_identity.mr_signer = msg3.msg3_body.report.body.mr_signer;
responder_identity.mr_enclave = msg3.msg3_body.report.body.mr_enclave;
Ok(())
}
fn dh_generate_message2(&self, msg1: &SgxDhMsg1, msg2: &mut SgxDhMsg2) -> SgxError {
msg2.report = Default::default();
msg2.cmac = Default::default();
msg2.g_b = self.pub_key;
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&msg1.g_a));
try!(sha_handle.update_msg(&msg2.g_b));
let msg_hash = try!(sha_handle.get_hash());
let mut report_data = sgx_report_data_t::default();
report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
report_data.d[SGX_SHA256_HASH_SIZE..SGX_SHA256_HASH_SIZE + 2].copy_from_slice(&AES_CMAC_KDF_ID);
let target = msg1.target;
msg2.report = try!(rsgx_create_report(&target, &report_data));
let report = msg2.report;
msg2.cmac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &report));
Ok(())
}
fn lav2_generate_message2(&self, msg1: &SgxDhMsg1, msg2: &mut SgxDhMsg2) -> SgxError {
msg2.report = Default::default();
msg2.cmac = Default::default();
msg2.g_b = self.pub_key;
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&SGX_LAV2_PROTO_SPEC));
try!(sha_handle.update_msg(&msg2.g_b));
let msg_hash = try!(sha_handle.get_hash());
let target = msg1.target;
let mut report_data = sgx_report_data_t::default();
report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
msg2.report = try!(rsgx_create_report(&target, &report_data));
unsafe {msg2.report.body.report_data = SGX_LAV2_PROTO_SPEC.to_report_data();}
msg2.cmac = try!(rsgx_rijndael128_cmac_msg(&self.smk_aek, &msg2.g_b));
Ok(())
}
fn dh_verify_message3(&self, msg3: &SgxDhMsg3) -> SgxError {
let add_prop_len = msg3.msg3_body.additional_prop.len() as u32;
let cmac_handle = SgxCmacHandle::new();
try!(cmac_handle.init(&self.smk_aek));
try!(cmac_handle.update_msg(&msg3.msg3_body.report));
try!(cmac_handle.update_msg(&add_prop_len));
if add_prop_len > 0 {
try!(cmac_handle.update_slice(&msg3.msg3_body.additional_prop));
}
let data_mac = try!(cmac_handle.get_hash());
if !data_mac.consttime_memeq(&msg3.cmac) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
try!(rsgx_verify_report(&msg3.msg3_body.report));
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&self.pub_key));
try!(sha_handle.update_msg(&self.peer_pub_key));
let msg_hash = try!(sha_handle.get_hash());
let data_hash = &msg3.msg3_body.report.body.report_data.d[..SGX_SHA256_HASH_SIZE];
if !msg_hash.eq(data_hash) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
Ok(())
}
fn lav2_verify_message3(&self, msg3: &SgxDhMsg3) -> SgxError {
let sha_handle = SgxShaHandle::new();
try!(sha_handle.init());
try!(sha_handle.update_msg(&self.peer_pub_key));
try!(sha_handle.update_msg(&SGX_LAV2_PROTO_SPEC));
let msg_hash = try!(sha_handle.get_hash());
let mut report = msg3.msg3_body.report;
report.body.report_data = sgx_report_data_t::default();
report.body.report_data.d[..SGX_SHA256_HASH_SIZE].copy_from_slice(&msg_hash);
if !&report.body.report_data.d[..].eq(&msg3.msg3_body.report.body.report_data.d[..]) {
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
}
try!(rsgx_verify_report(&report));
let cmac_handle = SgxCmacHandle::new();
try!(cmac_handle.init(&self.smk_aek));
if msg3.msg3_body.additional_prop.len() > 0 {
try!(cmac_handle.update_slice(&msg3.msg3_body.additional_prop));
}
try!(cmac_handle.update_msg(&self.peer_pub_key));
let data_mac = try!(cmac_handle.get_hash());
if !data_mac.consttime_memeq(&msg3.cmac) {
return Err(sgx_status_t::SGX_ERROR_MAC_MISMATCH);
}
Ok(())
}
fn set_error(&mut self, sgx_ret: sgx_status_t) -> sgx_status_t {
*self = Self::default();
self.state = SgxDhSessionState::SGX_DH_SESSION_STATE_ERROR;
match sgx_ret {
sgx_status_t::SGX_ERROR_OUT_OF_MEMORY => sgx_status_t::SGX_ERROR_OUT_OF_MEMORY,
_ => sgx_status_t::SGX_ERROR_UNEXPECTED,
}
}
}
#[derive(Copy, Clone, Default)]
struct SgxLAv2ProtoSpec {
signature: [u8; 6],
ver: u8,
rev: u8,
target_spec: [u16; 28],
}
unsafe impl ContiguousMemory for SgxLAv2ProtoSpec {}
impl SgxLAv2ProtoSpec {
pub unsafe fn to_report_data(&self) -> sgx_report_data_t {
mem::transmute::<SgxLAv2ProtoSpec, sgx_report_data_t>(*self)
}
pub unsafe fn from_report_data(data: &sgx_report_data_t) -> Self {
mem::transmute::<sgx_report_data_t, SgxLAv2ProtoSpec>(*data)
}
pub fn ts_count(&self) -> u16 {
self.target_spec[0] >> 8
}
pub fn is_valid(&self) -> bool {
self.ver == 2 && self.rev == 0 && self.target_spec[0] as u8 == 0 && self.ts_count() < 28
}
pub fn make_target_info(&self, rpt: &sgx_report_t, ti: &mut sgx_target_info_t) -> SgxError {
if !self.is_valid() {
return Err(sgx_status_t::SGX_ERROR_INVALID_PARAMETER);
}
let d = ti as * mut sgx_target_info_t as * mut u8;
let f = rpt as * const sgx_report_t as * const u8;
rsgx_lfence();
let mut to: i32 = 0;
for i in 1..(self.ts_count() + 1) as usize {
let size: i32 = 1 << (self.target_spec[i] & 0xF);
to += size - 1;
to &= -size;
if (to + size) as usize > mem::size_of::<sgx_target_info_t>() {
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
}
let from: i32 = (self.target_spec[i] >> 4) as i32;
if from >= 0 {
if (from + size) as usize > mem::size_of::<sgx_report_t>() {
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
}
unsafe {
ptr::copy_nonoverlapping(f.offset(from as isize), d.offset(to as isize), size as usize);
}
} else {
if from == -1 {
break;
} else {
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
}
}
to += size;
}
Ok(())
}
}
const SGX_LAV2_PROTO_SPEC: SgxLAv2ProtoSpec = SgxLAv2ProtoSpec {
signature: [0x53, 0x47, 0x58, 0x20, 0x4C, 0x41],
ver: 2,
rev: 0,
target_spec: [0x0600,
0x0405,
0x0304,
0x0140,
0x1041,
0x0102,
0x0C06,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
};
pub fn rsgx_self_target() -> SgxResult<sgx_target_info_t> {
let mut target_info = sgx_target_info_t::default();
let report = rsgx_self_report();
SGX_LAV2_PROTO_SPEC.make_target_info(&report, &mut target_info).map(|_| target_info)
}