This is an automated email from the ASF dual-hosted git repository.
uraj pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/develop by this push:
new 0aee807 [attestation] Generalize RA data structures to unify IAS and
DCAP (#214)
0aee807 is described below
commit 0aee807f5962f8d194a735b1288221a36149c87c
Author: Pei Wang <[email protected]>
AuthorDate: Mon Feb 3 10:50:40 2020 -0800
[attestation] Generalize RA data structures to unify IAS and DCAP (#214)
[attestation] Generalize RA data structures to unify IAS and DCAP
---
attestation/src/attestation.rs | 15 ++-
attestation/src/ias.rs | 80 ++++--------
attestation/src/lib.rs | 43 ++++++-
attestation/src/platform.rs | 97 ++++++--------
attestation/src/report.rs | 196 ++++++++++++++++++-----------
attestation/src/verifier.rs | 10 +-
binder/Enclave.edl | 21 ++--
binder/src/ocall.rs | 101 +++++++++------
services/authentication/enclave/src/lib.rs | 8 +-
services/database/enclave/src/lib.rs | 9 +-
services/execution/enclave/src/lib.rs | 9 +-
services/frontend/enclave/src/lib.rs | 9 +-
12 files changed, 333 insertions(+), 265 deletions(-)
diff --git a/attestation/src/attestation.rs b/attestation/src/attestation.rs
index d2d6a70..3c79e3e 100644
--- a/attestation/src/attestation.rs
+++ b/attestation/src/attestation.rs
@@ -1,5 +1,6 @@
use crate::key;
-use crate::IasReport;
+use crate::AttestationConfig;
+use crate::EndorsedAttestationReport;
use anyhow::Result;
use std::prelude::v1::*;
use std::time::{self, SystemTime};
@@ -15,12 +16,14 @@ pub struct RemoteAttestation {
}
impl RemoteAttestation {
- pub fn generate_and_endorse(ias_key: &str, ias_spid: &str) -> Result<Self>
{
+ pub fn generate_and_endorse(att_config: &AttestationConfig) ->
Result<Self> {
let key_pair = key::Secp256k1KeyPair::new()?;
- let report = if cfg!(sgx_sim) {
- IasReport::default()
- } else {
- IasReport::new(key_pair.pub_k, ias_key, ias_spid)?
+ let report = match att_config {
+ AttestationConfig::NoAttestation =>
EndorsedAttestationReport::default(),
+ AttestationConfig::SgxIas(config) => {
+ EndorsedAttestationReport::from_ias(key_pair.pub_k,
&config.api_key, &config.spid)?
+ }
+ AttestationConfig::SgxDcap(_) => unimplemented!(),
};
let cert_extension = serde_json::to_vec(&report)?;
diff --git a/attestation/src/ias.rs b/attestation/src/ias.rs
index bfec65a..28e90b8 100644
--- a/attestation/src/ias.rs
+++ b/attestation/src/ias.rs
@@ -16,7 +16,7 @@
// under the License.
use crate::AttestationError;
-use crate::IasReport;
+use crate::EndorsedAttestationReport;
use anyhow::Error;
use anyhow::Result;
use anyhow::{anyhow, bail};
@@ -34,18 +34,24 @@ extern "C" {
fn ocall_sgx_get_ias_socket(p_retval: *mut i32) -> sgx_status_t;
}
-impl IasReport {
- pub(crate) fn new(
+impl EndorsedAttestationReport {
+ pub(crate) fn from_ias(
pub_k: sgx_types::sgx_ec256_public_t,
ias_key: &str,
- ias_spid: &str,
+ ias_spid: &sgx_spid_t,
) -> anyhow::Result<Self> {
use crate::platform;
- let (target_info, epid_group_id) = platform::init_sgx_quote()?;
let mut ias_client = IasClient::new(ias_key);
- let sigrl = ias_client.get_sigrl(u32::from_le_bytes(epid_group_id))?;
- let sgx_report = platform::create_sgx_report(pub_k, target_info)?;
- let quote = platform::get_sgx_quote(&sigrl, sgx_report, target_info,
ias_spid)?;
+ let (mut ak_id, qe_target_info) = platform::init_sgx_quote()?;
+
+ // For IAS-based attestation, we need to fill our SPID (obtained from
Intel)
+ // into the attestation key id.
+ const SPID_OFFSET: usize = std::mem::size_of::<sgx_ql_att_key_id_t>();
+ ak_id.att_key_id[SPID_OFFSET..(SPID_OFFSET + ias_spid.id.len())]
+ .clone_from_slice(&ias_spid.id);
+
+ let sgx_report = platform::create_sgx_isv_enclave_report(pub_k,
qe_target_info)?;
+ let quote = platform::get_sgx_quote(&ak_id, sgx_report)?;
let ias_report = ias_client.get_report("e)?;
Ok(ias_report)
}
@@ -83,51 +89,7 @@ impl IasClient {
Ok(stream)
}
- fn get_sigrl(&mut self, epid_group_id: u32) -> Result<Vec<u8>> {
- let sigrl_uri = format!("/sgx/dev/attestation/v3/sigrl/{:08x}",
epid_group_id);
- let request = format!(
- "GET {} HTTP/1.1\r\n\
- HOST: {}\r\n\
- Ocp-Apim-Subscription-Key: {}\r\n\
- Connection: Close\r\n\r\n",
- sigrl_uri, self.ias_hostname, self.ias_key
- );
-
- let mut stream = self.new_tls_stream()?;
- stream.write_all(request.as_bytes())?;
- let mut response = Vec::new();
- stream.read_to_end(&mut response)?;
-
- let mut headers = [httparse::EMPTY_HEADER; 16];
- let mut http_response = httparse::Response::new(&mut headers);
- let header_len = match http_response
- .parse(&response)
- .map_err(|_| Error::new(AttestationError::IasError))?
- {
- httparse::Status::Complete(s) => s,
- _ => bail!(AttestationError::IasError),
- };
-
- let header_map = parse_headers(&http_response);
-
- if !header_map.contains_key("Content-Length")
- || header_map
- .get("Content-Length")
- .unwrap()
- .parse::<u32>()
- .unwrap_or(0)
- == 0
- {
- Ok(Vec::new())
- } else {
- let base64 = std::str::from_utf8(&response[header_len..])?;
-
- let decoded = base64::decode(base64)?;
- Ok(decoded)
- }
- }
-
- fn get_report(&mut self, quote: &[u8]) -> Result<IasReport> {
+ fn get_report(&mut self, quote: &[u8]) ->
Result<EndorsedAttestationReport> {
debug!("get_report");
let report_uri = "/sgx/dev/attestation/v3/report";
let encoded_quote = base64::encode(quote);
@@ -161,10 +123,10 @@ impl IasClient {
debug!("http_response.parse");
let header_len = match http_response
.parse(&response)
- .map_err(|_| Error::new(AttestationError::IasError))?
+ .map_err(|_|
Error::new(AttestationError::AttestationServiceError))?
{
httparse::Status::Complete(s) => s,
- _ => bail!(AttestationError::IasError),
+ _ => bail!(AttestationError::AttestationServiceError),
};
let header_map = parse_headers(&http_response);
@@ -178,19 +140,19 @@ impl IasClient {
.unwrap_or(0)
== 0
{
- bail!(AttestationError::IasError);
+ bail!(AttestationError::AttestationServiceError);
}
debug!("get_signature");
let signature = header_map
.get("X-IASReport-Signature")
- .ok_or_else(|| Error::new(AttestationError::IasError))?;
+ .ok_or_else(||
Error::new(AttestationError::AttestationServiceError))?;
let signature = base64::decode(signature)?;
debug!("get_signing_cert");
let signing_cert = {
let cert_str = header_map
.get("X-IASReport-Signing-Certificate")
- .ok_or_else(|| Error::new(AttestationError::IasError))?;
+ .ok_or_else(||
Error::new(AttestationError::AttestationServiceError))?;
let decoded_cert =
percent_encoding::percent_decode_str(cert_str).decode_utf8()?;
let certs = rustls::internal::pemfile::certs(&mut
decoded_cert.as_bytes())
.map_err(|_| anyhow!("pemfile error"))?;
@@ -198,7 +160,7 @@ impl IasClient {
};
let report = response[header_len..].to_vec();
- Ok(IasReport {
+ Ok(EndorsedAttestationReport {
report,
signature,
signing_cert,
diff --git a/attestation/src/lib.rs b/attestation/src/lib.rs
index d9f70e5..1c5acdf 100644
--- a/attestation/src/lib.rs
+++ b/attestation/src/lib.rs
@@ -27,18 +27,55 @@ use std::prelude::v1::*;
pub enum AttestationError {
#[error("OCall error")]
OCallError,
- #[error("IAS error")]
- IasError,
+ #[error("Attestation Service error")]
+ AttestationServiceError,
#[error("Platform error")]
PlatformError,
#[error("Report error")]
ReportError,
}
+pub enum AttestationConfig {
+ NoAttestation,
+ SgxIas(IasConfig),
+ SgxDcap(DcapConfig), // not supported yet
+}
+
+pub struct IasConfig {
+ pub api_key: String,
+ pub spid: sgx_types::sgx_spid_t,
+}
+
+pub struct DcapConfig {}
+
+impl AttestationConfig {
+ pub fn ias(ias_key: &str, ias_spid: &str) -> Self {
+ if cfg!(sgx_sim) {
+ Self::NoAttestation
+ } else {
+ use core::convert::TryFrom;
+
+ let mut spid = sgx_types::sgx_spid_t::default();
+ let hex = hex::decode(ias_spid).expect("Illegal SPID provided");
+ spid.id = <[u8; 16]>::try_from(hex.as_slice()).expect("Illegal
SPID provided");
+ Self::SgxIas(IasConfig {
+ api_key: ias_key.to_string(),
+ spid,
+ })
+ }
+ }
+}
+
+// AttestationReport can be endorsed by either the Intel Attestation Service
+// using EPID or Data Center Attestation Service (platform dependent) using
+// ECDSA.
#[derive(Default, Serialize, Deserialize)]
-pub(crate) struct IasReport {
+pub(crate) struct EndorsedAttestationReport {
+ // Attestation report generated by the hardware
pub report: Vec<u8>,
+ // Singature of the report
pub signature: Vec<u8>,
+ // Certificate matching the signing key of the signature
pub signing_cert: Vec<u8>,
}
diff --git a/attestation/src/platform.rs b/attestation/src/platform.rs
index f8fe306..9290396 100644
--- a/attestation/src/platform.rs
+++ b/attestation/src/platform.rs
@@ -14,47 +14,46 @@ use std::prelude::v1::*;
extern "C" {
fn ocall_sgx_init_quote(
p_retval: *mut sgx_status_t,
+ p_sgx_att_key_id: *mut sgx_att_key_id_t,
p_target_info: *mut sgx_target_info_t,
- p_gid: *mut sgx_epid_group_id_t,
) -> sgx_status_t;
- fn ocall_sgx_calc_quote_size(
+ fn ocall_sgx_get_quote_size(
p_retval: *mut sgx_status_t,
- p_sig_rl: *const u8,
- sig_rl_size: u32,
+ p_sgx_att_key_id: *const sgx_att_key_id_t,
p_quote_size: *mut u32,
) -> sgx_status_t;
fn ocall_sgx_get_quote(
p_retval: *mut sgx_status_t,
p_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_sig_rl: *const u8,
- sig_rl_size: u32,
- p_qe_report: *mut sgx_report_t,
+ p_sgx_att_key_id: *const sgx_att_key_id_t,
+ p_qe_report_info: *mut sgx_qe_report_info_t,
p_quote: *mut u8,
quote_size: u32,
) -> sgx_status_t;
}
-pub(crate) fn init_sgx_quote() -> Result<(sgx_target_info_t,
sgx_epid_group_id_t)> {
+pub(crate) fn init_sgx_quote() -> Result<(sgx_att_key_id_t,
sgx_target_info_t)> {
debug!("init_quote");
- let mut ti: sgx_target_info_t = sgx_target_info_t::default();
- let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default();
- let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED;
+ let mut ti = sgx_target_info_t::default();
+ let mut ak_id = sgx_att_key_id_t::default();
+ let mut rt = sgx_status_t::SGX_ERROR_UNEXPECTED;
- let res = unsafe { ocall_sgx_init_quote(&mut rt as _, &mut ti as _, &mut
eg as _) };
+ let res = unsafe { ocall_sgx_init_quote(&mut rt as _, &mut ak_id as _,
&mut ti as _) };
- if res != sgx_status_t::SGX_SUCCESS || rt != sgx_status_t::SGX_SUCCESS {
+ if res != sgx_status_t::SGX_SUCCESS {
bail!(AttestationError::OCallError)
- } else {
- Ok((ti, eg))
}
+
+ if rt != sgx_status_t::SGX_SUCCESS {
+ bail!(AttestationError::PlatformError)
+ }
+
+ Ok((ak_id, ti))
}
-pub(crate) fn create_sgx_report(
+pub(crate) fn create_sgx_isv_enclave_report(
pub_k: sgx_ec256_public_t,
target_info: sgx_target_info_t,
) -> Result<sgx_report_t> {
@@ -67,41 +66,31 @@ pub(crate) fn create_sgx_report(
report_data.d[..32].clone_from_slice(&pub_k_gx);
report_data.d[32..].clone_from_slice(&pub_k_gy);
- rsgx_create_report(&target_info, &report_data)
+ Ok(rsgx_create_report(&target_info, &report_data)
.map_err(|_| Error::new(AttestationError::PlatformError))
+ .unwrap())
}
-pub(crate) fn get_sgx_quote(
- sigrl: &[u8],
- report: sgx_report_t,
- target_info: sgx_target_info_t,
- ias_spid_str: &str,
-) -> Result<Vec<u8>> {
+pub(crate) fn get_sgx_quote(ak_id: &sgx_att_key_id_t, report: sgx_report_t) ->
Result<Vec<u8>> {
let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED;
- let (p_sigrl, sigrl_len) = if sigrl.is_empty() {
- (std::ptr::null(), 0)
- } else {
- (sigrl.as_ptr(), sigrl.len() as u32)
- };
let mut quote_len: u32 = 0;
- let res =
- unsafe { ocall_sgx_calc_quote_size(&mut rt as _, p_sigrl, sigrl_len,
&mut quote_len as _) };
+ let res = unsafe { ocall_sgx_get_quote_size(&mut rt as _, ak_id as _, &mut
quote_len as _) };
- if res != sgx_status_t::SGX_SUCCESS || rt != sgx_status_t::SGX_SUCCESS {
+ if res != sgx_status_t::SGX_SUCCESS {
bail!(AttestationError::OCallError);
}
- let mut quote_nonce = sgx_quote_nonce_t { rand: [0; 16] };
- let mut rng = SgxRng::new()?;
- rng.fill_bytes(&mut quote_nonce.rand);
- let mut qe_report = sgx_report_t::default();
+ if rt != sgx_status_t::SGX_SUCCESS {
+ bail!(AttestationError::PlatformError);
+ }
- let quote_type = sgx_quote_sign_type_t::SGX_LINKABLE_SIGNATURE;
+ let mut qe_report_info = sgx_qe_report_info_t::default();
+ let mut quote_nonce = sgx_quote_nonce_t::default();
- let mut spid = sgx_types::sgx_spid_t::default();
- let hex = hex::decode(ias_spid_str)?;
- spid.id.copy_from_slice(&hex[..16]);
+ let mut rng = SgxRng::new()?;
+ rng.fill_bytes(&mut quote_nonce.rand);
+ qe_report_info.nonce = quote_nonce;
let mut quote = vec![0; quote_len as usize];
@@ -110,12 +99,8 @@ pub(crate) fn get_sgx_quote(
ocall_sgx_get_quote(
&mut rt as _,
&report as _,
- quote_type,
- &spid as _,
- "e_nonce as _,
- p_sigrl,
- sigrl_len,
- &mut qe_report as _,
+ ak_id as _,
+ &mut qe_report_info as _,
quote.as_mut_ptr(),
quote_len,
)
@@ -126,16 +111,9 @@ pub(crate) fn get_sgx_quote(
}
debug!("rsgx_verify_report");
+ let qe_report = qe_report_info.qe_report;
// Perform a check on qe_report to verify if the qe_report is valid.
- rsgx_verify_report(&qe_report).map_err(|_|
Error::new(AttestationError::PlatformError))?;
-
- // Check if the qe_report is produced on the same platform.
- if target_info.mr_enclave.m != qe_report.body.mr_enclave.m
- || target_info.attributes.flags != qe_report.body.attributes.flags
- || target_info.attributes.xfrm != qe_report.body.attributes.xfrm
- {
- bail!(AttestationError::PlatformError);
- }
+ rsgx_verify_report(&qe_report).unwrap(); //map_err(|_|
Error::new(AttestationError::PlatformError)).expect("verify report failed");
// Check qe_report to defend against replay attack. The purpose of
// p_qe_report is for the ISV enclave to confirm the QUOTE it received
@@ -148,8 +126,9 @@ pub(crate) fn get_sgx_quote(
let mut rhs_vec: Vec<u8> = quote_nonce.rand.to_vec();
rhs_vec.extend("e);
debug!("rsgx_sha256_slice");
- let rhs_hash =
- rsgx_sha256_slice(&rhs_vec).map_err(|_|
Error::new(AttestationError::PlatformError))?;
+ let rhs_hash = rsgx_sha256_slice(&rhs_vec)
+ .map_err(|_| Error::new(AttestationError::PlatformError))
+ .expect("sha256 failed");
let lhs_hash = &qe_report.body.report_data.d[..32];
if rhs_hash != lhs_hash {
bail!(AttestationError::PlatformError);
diff --git a/attestation/src/report.rs b/attestation/src/report.rs
index c696fc2..b6c7dc3 100644
--- a/attestation/src/report.rs
+++ b/attestation/src/report.rs
@@ -20,7 +20,7 @@
use std::prelude::v1::*;
use crate::AttestationError;
-use crate::IasReport;
+use crate::EndorsedAttestationReport;
use anyhow::{anyhow, bail, ensure};
use anyhow::{Error, Result};
use chrono::DateTime;
@@ -50,7 +50,13 @@ static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[
&webpki::RSA_PKCS1_3072_8192_SHA384,
];
-pub struct SgxReport {
+// Do not confuse SgxEnclaveReport with AttestationReport.
+// SgxReport is generated by SGX hardware and endorsed by Quoting Enclave
through
+// local attestation. The endorsed SgxReport is an SGX quote. The quote is then
+// sent to some attestation service (IAS or DCAP-based AS). The endorsed SGX
quote
+// is an attestation report signed by attestation service private key, aka
+// EndorsedAttestationReport
+pub struct SgxEnclaveReport {
pub cpu_svn: [u8; 16],
pub misc_select: u32,
pub attributes: [u8; 16],
@@ -61,16 +67,91 @@ pub struct SgxReport {
pub report_data: [u8; 64],
}
+impl SgxEnclaveReport {
+ pub fn parse_from<'a>(bytes: &'a [u8]) -> Result<Self> {
+ let mut pos: usize = 0;
+ let mut take = |n: usize| -> Result<&'a [u8]> {
+ if n > 0 && bytes.len() >= pos + n {
+ let ret = &bytes[pos..pos + n];
+ pos += n;
+ Ok(ret)
+ } else {
+ bail!("Quote parsing error.")
+ }
+ };
+
+ // off 48, size 16
+ let cpu_svn = <[u8; 16]>::try_from(take(16)?)?;
+
+ // off 64, size 4
+ let misc_select = u32::from_le_bytes(<[u8; 4]>::try_from(take(4)?)?);
+
+ // off 68, size 28
+ let _reserved = take(28)?;
+
+ // off 96, size 16
+ let attributes = <[u8; 16]>::try_from(take(16)?)?;
+
+ // off 112, size 32
+ let mr_enclave = <[u8; 32]>::try_from(take(32)?)?;
+
+ // off 144, size 32
+ let _reserved = take(32)?;
+
+ // off 176, size 32
+ let mr_signer = <[u8; 32]>::try_from(take(32)?)?;
+
+ // off 208, size 96
+ let _reserved = take(96)?;
+
+ // off 304, size 2
+ let isv_prod_id = u16::from_le_bytes(<[u8; 2]>::try_from(take(2)?)?);
+
+ // off 306, size 2
+ let isv_svn = u16::from_le_bytes(<[u8; 2]>::try_from(take(2)?)?);
+
+ // off 308, size 60
+ let _reserved = take(60)?;
+
+ // off 368, size 64
+ let mut report_data = [0u8; 64];
+ let _report_data = take(64)?;
+ let mut _it = _report_data.iter();
+ for i in report_data.iter_mut() {
+ *i = *_it.next().ok_or_else(|| anyhow!("Quote parsing error."))?;
+ }
+
+ ensure!(pos == bytes.len(), "Quote parsing error.");
+
+ Ok(SgxEnclaveReport {
+ cpu_svn,
+ misc_select,
+ attributes,
+ mr_enclave,
+ mr_signer,
+ isv_prod_id,
+ isv_svn,
+ report_data,
+ })
+ }
+}
+
pub enum SgxQuoteVersion {
- V1,
- V2,
+ V1(SgxEpidQuoteSigType),
+ V2(SgxEpidQuoteSigType),
+ V3(SgxEcdsaQuoteAkType),
}
-pub enum SgxQuoteSigType {
+pub enum SgxEpidQuoteSigType {
Unlinkable,
Linkable,
}
+pub enum SgxEcdsaQuoteAkType {
+ P256_256,
+ P384_384,
+}
+
#[derive(PartialEq, Debug)]
pub enum SgxQuoteStatus {
OK,
@@ -90,18 +171,17 @@ impl From<&str> for SgxQuoteStatus {
}
}
-pub struct SgxQuoteBody {
+pub struct SgxQuote {
pub version: SgxQuoteVersion,
- pub signature_type: SgxQuoteSigType,
pub gid: u32,
pub isv_svn_qe: u16,
pub isv_svn_pce: u16,
pub qe_vendor_id: Uuid,
pub user_data: [u8; 20],
- pub report_body: SgxReport,
+ pub isv_enclave_report: SgxEnclaveReport,
}
-impl SgxQuoteBody {
+impl SgxQuote {
fn parse_from<'a>(bytes: &'a [u8]) -> Result<Self> {
let mut pos: usize = 0;
let mut take = |n: usize| -> Result<&'a [u8]> {
@@ -114,17 +194,33 @@ impl SgxQuoteBody {
}
};
- // off 0, size 2
+ // off 0, size 2 + 2
let version = match u16::from_le_bytes(<[u8; 2]>::try_from(take(2)?)?)
{
- 1 => SgxQuoteVersion::V1,
- 2 => SgxQuoteVersion::V2,
- _ => bail!("Quote parsing error."),
- };
-
- // off 2, size 2
- let signature_type = match u16::from_le_bytes(<[u8;
2]>::try_from(take(2)?)?) {
- 0 => SgxQuoteSigType::Unlinkable,
- 1 => SgxQuoteSigType::Linkable,
+ 1 => {
+ let signature_type = match u16::from_le_bytes(<[u8;
2]>::try_from(take(2)?)?) {
+ 0 => SgxEpidQuoteSigType::Unlinkable,
+ 1 => SgxEpidQuoteSigType::Linkable,
+ _ => bail!("Quote parsing error."),
+ };
+ SgxQuoteVersion::V1(signature_type)
+ }
+ 2 => {
+ let signature_type = match u16::from_le_bytes(<[u8;
2]>::try_from(take(2)?)?) {
+ 0 => SgxEpidQuoteSigType::Unlinkable,
+ 1 => SgxEpidQuoteSigType::Linkable,
+ _ => bail!("Quote parsing error."),
+ };
+ SgxQuoteVersion::V2(signature_type)
+ }
+ 3 => {
+ let attestation_key_type = match u16::from_le_bytes(<[u8;
2]>::try_from(take(2)?)?)
+ {
+ 2 => SgxEcdsaQuoteAkType::P256_256,
+ 3 => SgxEcdsaQuoteAkType::P384_384,
+ _ => bail!("Quote parsing error."),
+ };
+ SgxQuoteVersion::V3(attestation_key_type)
+ }
_ => bail!("Quote parsing error."),
};
@@ -144,67 +240,19 @@ impl SgxQuoteBody {
// off 28, size 20
let user_data = <[u8; 20]>::try_from(take(20)?)?;
- // off 48, size 16
- let cpu_svn = <[u8; 16]>::try_from(take(16)?)?;
-
- // off 64, size 4
- let misc_select = u32::from_le_bytes(<[u8; 4]>::try_from(take(4)?)?);
-
- // off 68, size 28
- let _reserved = take(28)?;
-
- // off 96, size 16
- let attributes = <[u8; 16]>::try_from(take(16)?)?;
-
- // off 112, size 32
- let mr_enclave = <[u8; 32]>::try_from(take(32)?)?;
-
- // off 144, size 32
- let _reserved = take(32)?;
-
- // off 176, size 32
- let mr_signer = <[u8; 32]>::try_from(take(32)?)?;
-
- // off 208, size 96
- let _reserved = take(96)?;
-
- // off 304, size 2
- let isv_prod_id = u16::from_le_bytes(<[u8; 2]>::try_from(take(2)?)?);
-
- // off 306, size 2
- let isv_svn = u16::from_le_bytes(<[u8; 2]>::try_from(take(2)?)?);
-
- // off 308, size 60
- let _reserved = take(60)?;
-
- // off 368, size 64
- let mut report_data = [0u8; 64];
- let _report_data = take(64)?;
- let mut _it = _report_data.iter();
- for i in report_data.iter_mut() {
- *i = *_it.next().ok_or_else(|| anyhow!("Quote parsing error."))?;
- }
+ // off 48, size 384
+ let isv_enclave_report = SgxEnclaveReport::parse_from(take(384)?)?;
ensure!(pos == bytes.len(), "Quote parsing error.");
Ok(Self {
version,
- signature_type,
gid,
isv_svn_qe,
isv_svn_pce,
qe_vendor_id,
user_data,
- report_body: SgxReport {
- cpu_svn,
- misc_select,
- attributes,
- mr_enclave,
- mr_signer,
- isv_prod_id,
- isv_svn,
- report_data,
- },
+ isv_enclave_report,
})
}
}
@@ -212,7 +260,7 @@ impl SgxQuoteBody {
pub struct AttestationReport {
pub freshness: Duration,
pub sgx_quote_status: SgxQuoteStatus,
- pub sgx_quote_body: SgxQuoteBody,
+ pub sgx_quote_body: SgxQuote,
}
impl AttestationReport {
@@ -232,7 +280,7 @@ impl AttestationReport {
let payload: Vec<u8> = ((sgx_ra_cert_ext.0).1).0;
- let report: IasReport = serde_json::from_slice(&payload)?;
+ let report: EndorsedAttestationReport =
serde_json::from_slice(&payload)?;
let signing_cert = webpki::EndEntityCert::from(&report.signing_cert)?;
let mut root_store = rustls::RootCertStore::empty();
@@ -295,7 +343,7 @@ impl AttestationReport {
.as_str()
.ok_or_else(|| Error::new(AttestationError::ReportError))?;
let quote_raw = base64::decode("e_encoded.as_bytes())?;
- SgxQuoteBody::parse_from(quote_raw.as_slice())?
+ SgxQuote::parse_from(quote_raw.as_slice())?
};
let raw_pub_k = pub_k.to_bytes();
@@ -311,7 +359,7 @@ impl AttestationReport {
// We only accept the uncompressed form here.
let is_uncompressed = raw_pub_k[0] == 4;
let pub_k = &raw_pub_k.as_slice()[1..];
- if !is_uncompressed || pub_k !=
&sgx_quote_body.report_body.report_data[..] {
+ if !is_uncompressed || pub_k !=
&sgx_quote_body.isv_enclave_report.report_data[..] {
bail!(AttestationError::ReportError);
}
diff --git a/attestation/src/verifier.rs b/attestation/src/verifier.rs
index d707f0d..8cfac14 100644
--- a/attestation/src/verifier.rs
+++ b/attestation/src/verifier.rs
@@ -46,8 +46,14 @@ impl AttestationReportVerifier {
fn verify_measures(&self, attestation_report: &AttestationReport) -> bool {
debug!("verify measures");
- let this_mr_signer =
attestation_report.sgx_quote_body.report_body.mr_signer;
- let this_mr_enclave =
attestation_report.sgx_quote_body.report_body.mr_enclave;
+ let this_mr_signer = attestation_report
+ .sgx_quote_body
+ .isv_enclave_report
+ .mr_signer;
+ let this_mr_enclave = attestation_report
+ .sgx_quote_body
+ .isv_enclave_report
+ .mr_enclave;
self.accepted_enclave_attrs.iter().any(|a| {
a.measurement.mr_signer == this_mr_signer &&
a.measurement.mr_enclave == this_mr_enclave
diff --git a/binder/Enclave.edl b/binder/Enclave.edl
index 16fd413..371821a 100644
--- a/binder/Enclave.edl
+++ b/binder/Enclave.edl
@@ -40,23 +40,18 @@ enclave {
include "sgx_quote.h"
untrusted {
- sgx_status_t ocall_sgx_init_quote([out] sgx_target_info_t
*p_target_info,
- [out] sgx_epid_group_id_t *p_gid);
-
int ocall_sgx_get_ias_socket();
- sgx_status_t ocall_sgx_calc_quote_size([in, size=sig_rl_size] uint8_t
* p_sig_rl,
- uint32_t sig_rl_size,
- [out] uint32_t *p_quote_size);
+ sgx_status_t ocall_sgx_init_quote([out] sgx_att_key_id_t *p_att_key_id,
+ [out] sgx_target_info_t
*p_target_info);
+
+ sgx_status_t ocall_sgx_get_quote_size([in] sgx_att_key_id_t
*p_att_key_id,
+ [out] uint32_t *p_quote_size);
sgx_status_t ocall_sgx_get_quote([in] sgx_report_t *p_report,
- sgx_quote_sign_type_t quote_type,
- [in] sgx_spid_t *p_spid,
- [in] sgx_quote_nonce_t *p_nonce,
- [in, size=sig_rl_size] uint8_t
*p_sig_rl,
- uint32_t sig_rl_size,
- [out] sgx_report_t *p_qe_report,
- [out, size=quote_size] sgx_quote_t
*p_quote,
+ [in] sgx_att_key_id_t *p_att_key_id,
+ [in, out] sgx_qe_report_info_t
*p_qe_report_info,
+ [out, size=quote_size] uint8_t
*p_quote,
uint32_t quote_size);
};
};
diff --git a/binder/src/ocall.rs b/binder/src/ocall.rs
index c3592dc..b8785e8 100644
--- a/binder/src/ocall.rs
+++ b/binder/src/ocall.rs
@@ -18,27 +18,30 @@
use sgx_types::*;
use std::net::TcpStream;
use std::os::unix::io::IntoRawFd;
+use std::ptr;
-#[link(name = "sgx_uae_service")]
+#[link(name = "sgx_quote_ex")]
extern "C" {
- fn sgx_init_quote(
- p_target_info: *mut sgx_target_info_t,
- p_gid: *mut sgx_epid_group_id_t,
+ fn sgx_select_att_key_id(
+ p_att_key_id_list: *const u8,
+ att_key_idlist_size: u32,
+ p_att_key_id: *mut sgx_att_key_id_t,
) -> sgx_status_t;
- fn sgx_calc_quote_size(
- p_sig_rl: *const u8,
- sig_rl_size: u32,
+ fn sgx_init_quote_ex(
+ p_att_key_id: *const sgx_att_key_id_t,
+ p_qe_target_info: *mut sgx_target_info_t,
+ p_pub_key_id_size: *mut usize,
+ p_pub_key_id: *mut u8,
+ ) -> sgx_status_t;
+ fn sgx_get_quote_size_ex(
+ p_att_key_id: *const sgx_att_key_id_t,
p_quote_size: *mut u32,
) -> sgx_status_t;
- fn sgx_get_quote(
- p_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_sig_rl: *const u8,
- sig_rl_size: u32,
- p_qe_report: *mut sgx_report_t,
- p_quote: *mut sgx_quote_t,
+ fn sgx_get_quote_ex(
+ p_isv_enclave_report: *const sgx_report_t,
+ p_att_key_id: *const sgx_att_key_id_t,
+ p_qe_report: *mut sgx_qe_report_info_t,
+ p_quote: *mut u8,
quote_size: u32,
) -> sgx_status_t;
}
@@ -54,43 +57,65 @@ pub extern "C" fn ocall_sgx_get_ias_socket() -> i32 {
#[no_mangle]
pub extern "C" fn ocall_sgx_init_quote(
- p_target_info: *mut sgx_target_info_t,
- p_gid: *mut sgx_epid_group_id_t,
+ p_att_key_id: *mut sgx_att_key_id_t,
+ p_qe_target_info: *mut sgx_target_info_t,
) -> sgx_status_t {
- unsafe { sgx_init_quote(p_target_info, p_gid) }
+ let ret = unsafe { sgx_select_att_key_id(ptr::null(), 0, p_att_key_id) };
+
+ if ret != sgx_status_t::SGX_SUCCESS {
+ return ret;
+ }
+
+ // First call to sgx_init_quote_ex to get att_pub_key_id_size
+ let mut att_pub_key_id_size = 0usize;
+ let ret = unsafe {
+ sgx_init_quote_ex(
+ p_att_key_id,
+ p_qe_target_info,
+ &mut att_pub_key_id_size as _,
+ ptr::null_mut(),
+ )
+ };
+
+ if ret != sgx_status_t::SGX_SUCCESS {
+ return ret;
+ }
+
+ // Second call to sgx_init_quote_ex to get att_pub_key_id
+ // At this point, it is unknown what att_pub_key_id is used for.
+ let mut att_pub_key_id: Vec<u8> = vec![0u8; att_pub_key_id_size];
+ unsafe {
+ sgx_init_quote_ex(
+ p_att_key_id,
+ p_qe_target_info,
+ &mut att_pub_key_id_size as _,
+ att_pub_key_id.as_mut_ptr(),
+ )
+ }
}
#[no_mangle]
-pub extern "C" fn ocall_sgx_calc_quote_size(
- p_sig_rl: *const u8,
- sig_rl_size: u32,
+pub extern "C" fn ocall_sgx_get_quote_size(
+ p_att_key_id: *const sgx_att_key_id_t,
p_quote_size: *mut u32,
) -> sgx_status_t {
- unsafe { sgx_calc_quote_size(p_sig_rl, sig_rl_size, p_quote_size) }
+ unsafe { sgx_get_quote_size_ex(p_att_key_id as _, p_quote_size) }
}
#[no_mangle]
pub extern "C" fn ocall_sgx_get_quote(
p_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_sig_rl: *const u8,
- sig_rl_size: u32,
- p_qe_report: *mut sgx_report_t,
- p_quote: *mut sgx_quote_t,
+ p_att_key_id: *const sgx_att_key_id_t,
+ p_qe_report_info: *mut sgx_qe_report_info_t,
+ p_quote: *mut u8,
quote_size: u32,
) -> sgx_status_t {
unsafe {
- sgx_get_quote(
+ sgx_get_quote_ex(
p_report,
- quote_type,
- p_spid,
- p_nonce,
- p_sig_rl,
- sig_rl_size,
- p_qe_report,
- p_quote,
+ p_att_key_id,
+ p_qe_report_info,
+ p_quote as _,
quote_size,
)
}
diff --git a/services/authentication/enclave/src/lib.rs
b/services/authentication/enclave/src/lib.rs
index 3ff710c..0e11bb7 100644
--- a/services/authentication/enclave/src/lib.rs
+++ b/services/authentication/enclave/src/lib.rs
@@ -28,7 +28,7 @@ use rand::RngCore;
use std::prelude::v1::*;
use std::sync::Arc;
use std::thread;
-use teaclave_attestation::RemoteAttestation;
+use teaclave_attestation::{AttestationConfig, RemoteAttestation};
use teaclave_ipc::proto::{
ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput,
InitEnclaveInput, InitEnclaveOutput,
StartServiceInput, StartServiceOutput,
@@ -109,7 +109,11 @@ fn handle_start_service(args: &StartServiceInput) ->
Result<StartServiceOutput>
let internal_listen_address =
args.config.internal_endpoints.authentication.listen_address;
let ias_config = args.config.ias.as_ref().unwrap();
let attestation = Arc::new(
- RemoteAttestation::generate_and_endorse(&ias_config.ias_key,
&ias_config.ias_spid).unwrap(),
+ RemoteAttestation::generate_and_endorse(&AttestationConfig::ias(
+ &ias_config.ias_key,
+ &ias_config.ias_spid,
+ ))
+ .unwrap(),
);
let database = user_db::Database::open()?;
let mut api_jwt_secret = vec![0; user_info::JWT_SECRET_LEN];
diff --git a/services/database/enclave/src/lib.rs
b/services/database/enclave/src/lib.rs
index 1c83c71..5c4a98e 100644
--- a/services/database/enclave/src/lib.rs
+++ b/services/database/enclave/src/lib.rs
@@ -36,7 +36,7 @@ use teaclave_ipc::{handle_ecall, register_ecall_handler};
use teaclave_service_enclave_utils::ServiceEnclave;
use rusty_leveldb::DB;
-use teaclave_attestation::RemoteAttestation;
+use teaclave_attestation::{AttestationConfig, RemoteAttestation};
use teaclave_proto::teaclave_database_service::{
TeaclaveDatabaseRequest, TeaclaveDatabaseResponse,
};
@@ -55,8 +55,11 @@ fn handle_start_service(args: &StartServiceInput) ->
Result<StartServiceOutput>
debug!("handle_start_service");
let listen_address = args.config.internal_endpoints.dbs.listen_address;
let ias_config = args.config.ias.as_ref().unwrap();
- let attestation =
- RemoteAttestation::generate_and_endorse(&ias_config.ias_key,
&ias_config.ias_spid).unwrap();
+ let attestation =
RemoteAttestation::generate_and_endorse(&AttestationConfig::ias(
+ &ias_config.ias_key,
+ &ias_config.ias_spid,
+ ))
+ .unwrap();
let config = SgxTrustedTlsServerConfig::new_without_verifier(
&attestation.cert,
&attestation.private_key,
diff --git a/services/execution/enclave/src/lib.rs
b/services/execution/enclave/src/lib.rs
index ebc9721..086c733 100644
--- a/services/execution/enclave/src/lib.rs
+++ b/services/execution/enclave/src/lib.rs
@@ -37,7 +37,7 @@ use teaclave_ipc::{handle_ecall, register_ecall_handler};
use teaclave_service_enclave_utils::ServiceEnclave;
-use teaclave_attestation::RemoteAttestation;
+use teaclave_attestation::{AttestationConfig, RemoteAttestation};
use teaclave_proto::teaclave_execution_service::{
TeaclaveExecutionRequest, TeaclaveExecutionResponse,
};
@@ -55,8 +55,11 @@ register_ecall_handler!(
fn handle_start_service(args: &StartServiceInput) ->
Result<StartServiceOutput> {
let listen_address =
args.config.internal_endpoints.execution.listen_address;
let ias_config = args.config.ias.as_ref().unwrap();
- let attestation =
- RemoteAttestation::generate_and_endorse(&ias_config.ias_key,
&ias_config.ias_spid).unwrap();
+ let attestation =
RemoteAttestation::generate_and_endorse(&AttestationConfig::ias(
+ &ias_config.ias_key,
+ &ias_config.ias_spid,
+ ))
+ .unwrap();
let config = SgxTrustedTlsServerConfig::new_without_verifier(
&attestation.cert,
&attestation.private_key,
diff --git a/services/frontend/enclave/src/lib.rs
b/services/frontend/enclave/src/lib.rs
index 3932527..febdee7 100644
--- a/services/frontend/enclave/src/lib.rs
+++ b/services/frontend/enclave/src/lib.rs
@@ -25,7 +25,7 @@ extern crate log;
use anyhow::Result;
use std::prelude::v1::*;
-use teaclave_attestation::RemoteAttestation;
+use teaclave_attestation::{AttestationConfig, RemoteAttestation};
use teaclave_ipc::proto::{
ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput,
InitEnclaveInput, InitEnclaveOutput,
StartServiceInput, StartServiceOutput,
@@ -45,8 +45,11 @@ fn handle_start_service(args: &StartServiceInput) ->
Result<StartServiceOutput>
debug!("handle_start_service");
let listen_address = args.config.api_endpoints.frontend.listen_address;
let ias_config = args.config.ias.as_ref().unwrap();
- let attestation =
- RemoteAttestation::generate_and_endorse(&ias_config.ias_key,
&ias_config.ias_spid).unwrap();
+ let attestation =
RemoteAttestation::generate_and_endorse(&AttestationConfig::ias(
+ &ias_config.ias_key,
+ &ias_config.ias_spid,
+ ))
+ .unwrap();
let config = SgxTrustedTlsServerConfig::new_without_verifier(
&attestation.cert,
&attestation.private_key,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]