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(&quote)?;
         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 _,
-            &quote_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(&quote);
     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(&quote_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]

Reply via email to